Was ist der Unterschied zwischen Linux GNU C und ANSI C?
Der unter Linux verfügbare C-Compiler ist der GNU C-Compiler, der auf der Programmierlizenz der Free Software Foundation basiert und daher frei verbreitet und verwendet werden kann. GNU C führt eine Reihe von Erweiterungen zu Standard C durch, um die Funktionalität von Standard C zu verbessern.
1. Arrays mit Nulllänge und variabler Länge
GNU C ermöglicht die Verwendung von Arrays mit der Länge Null, was beim Definieren der Header-Struktur von Objekten variabler Länge sehr nützlich ist. Zum Beispiel:
struct var_data { int len; char data[0]; };
char data[0] bedeutet nur, dass das Programm über das data[index]-Mitglied der var_data-Strukturinstanz auf die Indexadresse zugreifen kann. Es reserviert keinen Speicher für das data[]-Array, also sizeof (struct var_data) = sizeof(int).
Angenommen, das Datenfeld der Struktur var_data wird im Speicherbereich gespeichert, der unmittelbar auf die Struktur var_data folgt, können die Daten mit dem folgenden Code durchlaufen werden:
struct var_data s; ... for (i = 0; i printf("%02x", s.data[i]);
In GNU C können Sie auch eine Variable verwenden, um ein Array zu definieren, z. B. „double x[n]“, definiert im folgenden Code:
int main (int argc, char *argv[]) { int i, n = argc; double x[n]; for (i = 0; i return 0; }
2.Fallumfang
GNU C unterstützt die Syntax von Fall x...y. Die Zahlen im Intervall [x, y] erfüllen die Bedingungen dieses Falls:
switch (ch) { case '0'... '9': c -= '0'; break; case 'a'... 'f': c -= 'a' - 10; break; case 'A'... 'F': c -= 'A' - 10; break; }
case '0'...'9' im Code entspricht dem in Standard-C:
case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
3. Aussageausdruck
GNU C behandelt die in Klammern enthaltene zusammengesetzte Anweisung als einen Ausdruck, der als Anweisungsausdruck bezeichnet wird und überall dort erscheinen kann, wo Ausdrücke zulässig sind. Wir können Schleifen, lokale Variablen usw. verwenden, die nur in zusammengesetzten Anweisungen in Anweisungsausdrücken verwendet werden können, zum Beispiel:
#define min_t(type,x,y) \ ( { type _ _x =(x);type _ _y = (y); _ _xfloat fa, fb, minf; mini = min_t(int, ia, ib); minf = min_t(float, fa, fb);
Da die beiden lokalen Variablen __xx und __y neu definiert werden, haben auf die oben beschriebene Weise definierte Makros keine Nebenwirkungen. In Standard C erzeugen die entsprechenden Makros unten Nebenwirkungen:
#define min(x,y) ((x)
Der Code min(++ia,++ib) wird erweitert zu ((++ia)
4.Typ des Schlüsselworts
Die typeof(x)-Anweisung kann den Typ von x erhalten. Daher kann das Min-Makro mit Hilfe von typeof neu definiert werden:
#define min(x,y) ({ \ const typeof(x) _x = (x); \ const typeof(y) _y = (y); \ (void) (&_x == &_y); \ _x
Wir müssen keinen Typ wie beim Makro min_t (type, x, y) übergeben, da der Typ über typeof (x), typeof (y) erhalten werden kann. Die Funktion der Codezeile (void) (&_x==&_y) besteht darin, zu prüfen, ob die Typen von _x und _y konsistent sind.
5. Makro mit variablen Parametern
Standard C unterstützt Funktionen mit variablen Parametern, was bedeutet, dass die Parameter der Funktion nicht festgelegt sind. Der Prototyp der printf()-Funktion lautet beispielsweise:
int printf( const char *format [, argument]... );
In GNU C können Makros auch eine variable Anzahl von Parametern akzeptieren, zum Beispiel:
#define pr_debug(fmt,arg...) \ printk(fmt,##arg)
Hier stellt arg die verbleibenden Parameter dar, die null oder mehr Parameter haben können, und die Kommas zwischen den Parametern bilden den Wert von arg, der während der Makroerweiterung ersetzt wird:
pr_debug("%s:%d",filename,line)
wird erweitert zu:
printk("%s:%d", filename, line)
Verwenden Sie „##“, um mit der Situation umzugehen, in der arg keinen Parameter darstellt. Zu diesem Zeitpunkt wird das vorangehende Komma überflüssig. Nach der Verwendung von „##“ verwirft der GNU C-Präprozessor das vorangehende Komma, sodass der folgende Code entsteht:
pr_debug("success!\n")
wird korrekt erweitert zu:
printk("success!\n")
statt:
printk("success!\n",)
6. Etikettenelemente
Standard C verlangt, dass die Initialisierungswerte eines Arrays oder einer Struktur in einer festen Reihenfolge erscheinen müssen. In GNU C dürfen Initialisierungswerte durch Angabe von Indizes oder Strukturmitgliedsnamen in beliebiger Reihenfolge erscheinen.
Der Array-Index kann durch Hinzufügen von „[INDEX]=" vor dem Initialisierungswert angegeben werden. Natürlich können Sie auch einen Bereich in der Form „[FIRST...LAST]=" angeben. Der folgende Code definiert beispielsweise ein Array und weist allen darin enthaltenen Elementen den Wert 0 zu:
unsigned char data[MAX] = { [0 ... MAX-1] = 0 };
Der folgende Code initialisiert die Struktur mithilfe von Strukturelementnamen:
struct file_operations ext2_file_operations = { llseek: generic_file_llseek, read: generic_file_read, write: generic_file_write, ioctl: ext2_ioctl, mmap: generic_file_mmap, open: generic_file_open, release: ext2_release_file, fsync: ext2_sync_file, };
Linux 2.6 empfiehlt jedoch, dass ähnlicher Code so weit wie möglich in Standard-C vorliegen sollte:
struct file_operations ext2_file_operations = { .llseek = generic_file_llseek, .read = generic_file_read, .write = generic_file_write, .aio_read = generic_file_aio_read, .aio_write = generic_file_aio_write, .ioct = ext2_ioctl, .mmap = generic_file_mmap, .open = generic_file_open, .release = ext2_release_file, .fsync = ext2_sync_file, .readv = generic_file_readv, .writev = generic_file_writev, .sendfile = generic_file_sendfile, };
7. Aktueller Funktionsname
GNU C definiert zwei Bezeichner vor, um den Namen der aktuellen Funktion zu speichern, __FUNCTION__ speichert den Namen der Funktion im Quellcode und __PRETTY_FUNCTION__ speichert den Namen mit Sprachmerkmalen. In der C-Funktion sind diese beiden Namen identisch.
void example() { printf("This is function:%s", __FUNCTION__); }
__FUNCTION__ im Code bedeutet die Zeichenfolge „Beispiel“. C99 unterstützt bereits das Makro __func__, daher wird empfohlen, __FUNCTION__ in der Linux-Programmierung nicht mehr zu verwenden und stattdessen __func__ zu verwenden:
void example(void) { printf("This is function:%s", __func__); }
8.特殊属性声明
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位。
9.内建函数
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'
Das obige ist der detaillierte Inhalt vonWas ist der Unterschied zwischen Linux GNU C und ANSI C?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Heiße KI -Werkzeuge

Undresser.AI Undress
KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover
Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool
Ausziehbilder kostenlos

Clothoff.io
KI-Kleiderentferner

AI Hentai Generator
Erstellen Sie kostenlos Ai Hentai.

Heißer Artikel

Heiße Werkzeuge

Notepad++7.3.1
Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version
Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1
Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6
Visuelle Webentwicklungstools

SublimeText3 Mac-Version
Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Heiße Themen



Um eine Web.xml -Datei zu öffnen, können Sie die folgenden Methoden verwenden: Verwenden Sie einen Texteditor (z.

Multithreading in der Sprache kann die Programmeffizienz erheblich verbessern. Es gibt vier Hauptmethoden, um Multithreading in C -Sprache zu implementieren: Erstellen Sie unabhängige Prozesse: Erstellen Sie mehrere unabhängig laufende Prozesse. Jeder Prozess hat seinen eigenen Speicherplatz. Pseudo-MultitHhreading: Erstellen Sie mehrere Ausführungsströme in einem Prozess, der denselben Speicherplatz freigibt und abwechselnd ausführt. Multi-Thread-Bibliothek: Verwenden Sie Multi-Thread-Bibliotheken wie PThreads, um Threads zu erstellen und zu verwalten, wodurch reichhaltige Funktionen der Thread-Betriebsfunktionen bereitgestellt werden. Coroutine: Eine leichte Multi-Thread-Implementierung, die Aufgaben in kleine Unteraufgaben unterteilt und sie wiederum ausführt.

Linux wird am besten als Serververwaltung, eingebettete Systeme und Desktop -Umgebungen verwendet. 1) In der Serververwaltung wird Linux verwendet, um Websites, Datenbanken und Anwendungen zu hosten und Stabilität und Zuverlässigkeit bereitzustellen. 2) In eingebetteten Systemen wird Linux aufgrund seiner Flexibilität und Stabilität in Smart Home und Automotive Electronic Systems häufig verwendet. 3) In der Desktop -Umgebung bietet Linux reichhaltige Anwendungen und eine effiziente Leistung.

Debianlinux ist bekannt für seine Stabilität und Sicherheit und wird in Server-, Entwicklungs- und Desktop -Umgebungen häufig verwendet. Während es derzeit einen Mangel an offiziellen Anweisungen zur direkten Kompatibilität mit Debian und Hadoop gibt, wird dieser Artikel Sie dazu veranlassen, Hadoop in Ihrem Debian -System bereitzustellen. Debian -Systemanforderungen: Bevor Sie mit der Hadoop -Konfiguration beginnen, stellen Sie bitte sicher, dass Ihr Debian -System die Mindestanforderungen von Hadoop erfüllt, einschließlich der Installation der erforderlichen Java -Laufzeitumgebung (JRE) und Hadoop -Pakete. Schritte zur Bereitstellung von Hadoop -Bereitstellungen: Download und Unzip Hadoop: Laden Sie die Hadoop -Version von der offiziellen Apachehadoop -Website herunter und lösen Sie sie

Muss ich einen Oracle -Client installieren, wenn ich mit GO eine Verbindung zu einer Oracle -Datenbank herstellen kann? Bei der Entwicklung in Go ist die Verbindung zu Oracle -Datenbanken eine übliche Anforderung ...

"DebianStrings" ist kein Standardbegriff und seine spezifische Bedeutung ist noch unklar. Dieser Artikel kann seine Browserkompatibilität nicht direkt kommentieren. Wenn sich jedoch "DebianStrings" auf eine Webanwendung bezieht, die auf einem Debian -System ausgeführt wird, hängt seine Browserkompatibilität von der technischen Architektur der Anwendung selbst ab. Die meisten modernen Webanwendungen sind für die Kompatibilität des Cross-Browsers verpflichtet. Dies beruht auf den folgenden Webstandards und der Verwendung gut kompatibler Front-End-Technologien (wie HTML, CSS, JavaScript) und Back-End-Technologien (wie PHP, Python, Node.js usw.). Um sicherzustellen, dass die Anwendung mit mehreren Browsern kompatibel ist, müssen Entwickler häufig Kreuzbrowser-Tests durchführen und die Reaktionsfähigkeit verwenden

Die Hauptgründe, warum Sie sich bei MySQL nicht als Root anmelden können, sind Berechtigungsprobleme, Konfigurationsdateifehler, Kennwort inkonsistent, Socket -Dateiprobleme oder Firewall -Interception. Die Lösung umfasst: Überprüfen Sie, ob der Parameter Bind-Address in der Konfigurationsdatei korrekt konfiguriert ist. Überprüfen Sie, ob die Root -Benutzerberechtigungen geändert oder gelöscht und zurückgesetzt wurden. Stellen Sie sicher, dass das Passwort korrekt ist, einschließlich Fall- und Sonderzeichen. Überprüfen Sie die Einstellungen und Pfade der Socket -Dateiberechtigte. Überprüfen Sie, ob die Firewall Verbindungen zum MySQL -Server blockiert.

Ich habe ein Projekt namens Lua-Libuv entwickelt und freue mich, meine Erfahrungen zu teilen. Die ursprüngliche Absicht des Projekts besteht darin, zu untersuchen, wie Libuv (eine in C geschriebene asynchrone E/A -Bibliothek) verwendet wird, um einen einfachen HTTP -Server zu erstellen, ohne die C -Sprache ausführlich lernen zu müssen. Mit Hilfe von ChatGPT habe ich den Basiscode von http.c. Beim Umgang mit anhaltenden Verbindungen habe ich zum richtigen Zeitpunkt erfolgreich die Schließung der Verbindung und die Freilegung von Ressourcen implementiert. Zuerst habe ich versucht, einen einfachen Server zu erstellen, der das Hauptprogramm beendete, indem ich die Verbindung schließt, aber ich hatte einige Probleme. Ich habe versucht, Datenblöcke mit Streaming zu senden, und während es funktioniert, blockiert dies den Haupt -Thread. Am Ende habe ich mich entschlossen, diesen Ansatz aufzugeben, weil mein Ziel nicht darin bestand, eine Tiefe der C -Sprache zu lernen. Endlich, ich
