התחביר המוזר של טיפוסי נתונים ב-C

ב-C יש עשרה טיפוסי נתונים בסיסיים:

  • signed/unsigned char
  • signed/unsigned short
  • signed/unsigned int
  • signed/unsigned long
  • float
  • double

  • מצביע לטיפוס נתון
  • מערך מטיפוס נתון
  • מצביע לפונקציה שמחזירה טיפוס נתון
  • רשומה (struct) שמורכבת מסדרה של שדות מטיפוסים נתונים
  • איחוד (union) של שדות מטיפוסים נתונים.

 

#include <stdio.h>
#include <stdlib.h>

int main() {
    int (*a)[12] = malloc(120 * sizeof(int));
    for (int i = 0; i < 10; i++) {
        for (int j = 0; j < 12; j++) {
            a[i][j] = i * j;
        }
    }
    printf("5 * 6 == %d", a[5][6]); // Prints: 5 * 6 == 30
    free(a);
    return 0;
}

מצביע לפונקציה

הנה עוד דוגמאות:

אם a הוא… …אז כדי לקבל int, נשתמש בביטוי… ולכן, כדי להצהיר על a, צריך לכתוב… הערות
מערך של 8 מצביעים לפונקציות שמחזירות int (*a[0])() int (*a[8])(); יש צורך בסוגריים כי בלעדיהם האופרטור () (קריאה לפונקציה) קודם לאופרטור * (dereference)

יש ב-C שתי דרכים להצהיר על פונקציה:

כאשר אנחנו מסתפקים בסוגריים ריקים אחרי שם הפונקציה, אנחנו בעצם אומרים לקומפיילר שאנחנו משתמשים בתחביר הישן, כלומר אנחנו לא מציינים את טיפוסי הפרמטרים ואפשר לקרוא לפונקציה עם כל רשימה של ארגומנטים אקטואליים, בלי שום חשיבות לטיפוסים ואפילו לא למספר הארגומנטים! אותו דבר נכון גם להצהרה על מצביע לפונקציה.

כל הדוגמאות הקודמות התייחסו מטעמי פשטות לתחביר הישן, זה שמבדיל בין טיפוסים שונים של פונקציות רק על סמך הטיפוס שהן מחזירות. כדי שהקומפיילר יבדוק גם את טיפוסי הארגומנטים האקטואליים ואת התאמתם לפרמטרים הפורמליים, יש לכתוב את טיפוסי הפרמטרים בתוך הסוגריים. אין צורך לתת שם לכל פרמטר אלא רק לכתוב את הטיפוס. כדי להצהיר או להגדיר פונקציה ללא פרמטרים, יש לכתוב void בתוך הסוגריים.

#include <stdio.h>
#include <stdlib.h>

/* K&R (old) syntax */
int foo() {
return 0;
}

/* ANSI (new) syntax */
int bar(void) {
return 0;
}

int frobozz(int a, int *b) {
return a * *b;
}

int main(void) {
int (*a)() = foo, (*b)() = bar, (*c)() = frobozz; // OK
int (*d)(void) = foo; // warning C4113: 'int (__cdecl *)()' differs in parameter lists from 'int (__cdecl *)(void)'
int (*e)(int, int *) = frobozz; // OK
int (*f)(void) = frobozz; // warning C4113: 'int (__cdecl *)(int,int *)' differs in parameter lists from 'int (__cdecl *)(void)'
int (*g)(int, int *) = foo; // warning C4113: 'int (__cdecl *)()' differs in parameter lists from 'int (__cdecl *)(int,int *)'
int (*h)(int, int *) = bar; // warning C4113: 'int (__cdecl *)(void)' differs in parameter lists from 'int (__cdecl *)(int,int *)'
return 0;
}

להשאיר תגובה

הזינו את פרטיכם בטופס, או לחצו על אחד מהאייקונים כדי להשתמש בחשבון קיים:

הלוגו של WordPress.com

אתה מגיב באמצעות חשבון WordPress.com שלך. לצאת מהמערכת /  לשנות )

תמונת גוגל

אתה מגיב באמצעות חשבון Google שלך. לצאת מהמערכת /  לשנות )

תמונת Twitter

אתה מגיב באמצעות חשבון Twitter שלך. לצאת מהמערכת /  לשנות )

תמונת Facebook

אתה מגיב באמצעות חשבון Facebook שלך. לצאת מהמערכת /  לשנות )

מתחבר ל-%s