Linux에서 사용할 수 있는 C 컴파일러는 GNU C 컴파일러로, 자유 소프트웨어 재단의 프로그래밍 라이센스를 기반으로 구축되었으므로 자유롭게 배포하고 사용할 수 있습니다. GNU C는 표준 C의 기능을 향상시키기 위해 표준 C에 대한 일련의 확장을 만듭니다.
GNU C에서는 길이가 0인 배열을 사용할 수 있는데, 이는 가변 길이 객체의 헤더 구조를 정의할 때 매우 유용합니다. 예:
으아아아char data[0]는 프로그램이 var_data 구조 인스턴스의 data[index] 멤버를 통해 len 이후의 인덱스 주소에 액세스할 수 있다는 것을 의미합니다. data[] 배열에 메모리를 할당하지 않으므로 sizeof(struct var_data) = 크기(정수).
struct var_data의 데이터 필드가 struct var_data 바로 뒤의 메모리 영역에 저장되어 있다고 가정하면 다음 코드를 통해 데이터를 탐색할 수 있습니다.
으아아아GNU C에서는 다음 코드에 정의된 "double x[n]"과 같이 변수 1개를 사용하여 배열을 정의할 수도 있습니다.
으아아아GNU C는 x...y 구문을 지원합니다. 간격 [x, y]의 숫자는 이 경우의 조건을 충족합니다.
으아아아코드의 '0'...'9' 사례는 표준 C의 사례와 동일합니다:
으아아아GNU C는 괄호 안에 포함된 복합 명령문을 명령문 표현식이라고 하는 표현식으로 처리합니다. 이 표현식은 표현식이 허용되는 모든 곳에 나타날 수 있습니다. 명령문 표현식의 복합 명령문에만 사용할 수 있는 루프, 지역 변수 등을 사용할 수 있습니다. 예:
으아아아두 개의 지역 변수 __xx와 __y가 재정의되기 때문에 위와 같은 방식으로 정의된 매크로는 부작용이 없습니다. 표준 C에서는 아래의 해당 매크로가 부작용을 발생시킵니다.
으아아아코드 min(++ia,++ib)은 ((++ia)로 확장됩니다.
typeof(x) 문은 x 유형을 얻을 수 있습니다. 따라서 min 매크로는 typeof를 사용하여 재정의할 수 있습니다.
으아아아typeof(x) 및 typeof(y)를 통해 유형을 얻을 수 있으므로 min_t(type, x, y) 매크로와 같은 유형을 전달할 필요가 없습니다. 코드 라인(void)(&_x==&_y)의 기능은 _x와 _y의 유형이 일치하는지 확인하는 것입니다.
표준 C는 가변 매개변수 함수를 지원합니다. 이는 함수의 매개변수가 고정되지 않음을 의미합니다. 예를 들어 printf() 함수의 프로토타입은 다음과 같습니다. 으아아아
GNU C에서 매크로는 가변 개수의 매개변수를 허용할 수도 있습니다. 예:으아아아
여기서 arg는 0개 이상의 매개변수를 가질 수 있는 나머지 매개변수를 나타냅니다. 이러한 매개변수와 매개변수 사이의 쉼표는 다음 코드와 같이 매크로 확장 중에 대체됩니다. 으아아아다음으로 확장됩니다.
으아아아arg가 어떤 매개변수도 나타내지 않는 상황을 처리하려면 "##"을 사용하세요. 이때 앞의 쉼표는 중복됩니다. "##"을 사용한 후 GNU C 전처리기는 앞의 쉼표를 삭제하므로 다음 코드는 다음과 같습니다.
으아아아는 다음과 같이 올바르게 확장됩니다.
으아아아대신:
으아아아 6. 라벨 요소배열 인덱스를 지정하는 방법은 초기화 값 앞에 "[INDEX]="를 추가하는 것입니다. 물론 "[FIRST...LAST]=" 형식으로 범위를 지정할 수도 있습니다. 예를 들어, 다음 코드는 배열을 정의하고 그 안의 모든 요소를 0에 할당합니다.
으아아아다음 코드는 구조체 멤버 이름을 사용하여 구조체를 초기화합니다.
으아아아그러나 Linux 2.6에서는 유사한 코드가 가능한 한 표준 C에 있어야 한다고 권장합니다.
으아아아 7. 현재 함수 이름__FUNCTION__은 "example"이라는 문자열을 의미합니다. C99는 이미 __func__ 매크로를 지원하므로 Linux 프로그래밍에서는 더 이상 __FUNCTION__을 사용하지 않고 대신 __func__을 사용하는 것이 좋습니다.
void example(void) { printf("This is function:%s", __func__); }
GNU C允许声明函数、变量和类型的特殊属性,以便手动优化代码和定制代码检查的方法。要指定一个声明的 属性,只需要在声明后添加__attribute__((ATTRIBUTE))。其中ATTRIBUTE为属性说明,如果存在多个属 性,则以逗号分隔。GNU C支持noreturn、format、section、aligned、packed等十多个属性。
noreturn属性作用于函数,表示该函数从不返回。这会让编译器优化代码,并消除不必要的警告信息。例如:
# define ATTRIB_NORET __attribute__((noreturn)) .... asmlinkage NORET_TYPE void do_exit(long error_code) ATTRIB_NORET;
format属性也用于函数,表示该函数使用printf、scanf或strftime风格的参数,指定format属性可以让编译器根据格 式串检查参数类型。例如:
asmlinkage int printk(const char * fmt, ...) __attribute__ ((format (printf, 1, 2)));
上述代码中的第1个参数是格式串,从第2个参数开始都会根据printf()函数的格式串规则检查参数。
unused属性作用于函数和变量,表示该函数或变量可能不会用到,这个属性可以避免编译器产生警告信息。
aligned属性用于变量、结构体或联合体,指定变量、结构体或联合体的对齐方式,以字节为单位,例如:
struct example_struct { char a; int b; long c; } __attribute__((aligned(4)));
表示该结构类型的变量以4字节对齐。
packed属性作用于变量和类型,用于变量或结构体成员时表示使用最小可能的对齐,用于枚举、结构体或联合体类型时表示该类型使用最小的内存。例如:
struct example_struct { char a; int b; long c __attribute__((packed)); };
编译器对结构体成员及变量对齐的目的是为了更快地访问结构体成员及变量占据的内存。例如,对 于一个32位的整型变量,若以4字节方式存放(即低两位地址为00),则CPU在一个总线周期内就可以读取32 位;否则,CPU需要两个总线周期才能读取32位。
GNU C提供了大量内建函数,其中大部分是标准C库函数的GNU C编译器内建版本,例如memcpy()等,它们与对应的标准C库函数功能相同。
不属于库函数的其他内建函数的命名通常以__builtin开始,如下所示。
内建函数__builtin_return_address(LEVEL)返回当前函数或其调用者的返回地址,参数LEVEL指定调用栈的级数,如0表示当前函数的返回地址,1表示当前函数的调用者的返回地址。
内建函数__builtin_constant_p(EXP)用于判断一个值是否为编译时常数,如果参数EXP的值是常数,函数返回1,否则返回0。例如,下面的代码可检测第1个参数是否为编译时常数以确定采用参数版本还是非参数版本:
#define test_bit(nr,addr) \ (__builtin_constant_p(nr) \ constant_test_bit((nr),(addr)) : \ variable_test_bit((nr),(addr)))
内建函数__builtin_expect(EXP,C)用于为编译器提供分支预测信息,其返回值是整数表达式EXP的值,C的 值必须是编译时常数。
Linux内核编程时常用的likely()和unlikely()底层调用的likely_notrace()、unlikely_notrace()就是基于 __builtin_expect(EXP,C)实现的。
#define likely_notrace(x) __builtin_expect(!!(x), 1) #define unlikely_notrace(x) __builtin_expect(!!(x), 0)
若代码中出现分支,则即可能中断流水线,我们可以通过likely()和unlikely()暗示分支容易成立还是不容易 成立,例如:
if (likely(!IN_DEV_ROUTE_LOCALNET(in_dev))) if (ipv4_is_loopback(saddr)) goto e_inval;
在使用gcc编译C程序的时候,如果使用“-ansi–pedantic”编译选项,则会告诉编译器不使用GNU扩展语法。例如对 于如下C程序test.c:
struct var_data { int len; char data[0]; }; struct var_data a;
直接编译可以通过:
gcc -c test.c
如果使用“-ansi–pedantic”编译选项,编译会报警:
gcc -ansi -pedantic -c test.c test.c:3: warning: ISO C forbids zero-size array 'data'
위 내용은 Linux GNU C와 ANSI C의 차이점은 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!