Bu C kodunun çıktısı 49'dur, ancak birisi bana nasıl olduğunu açıklayabilir mi? [çiftleme]
#include <stdio.h>
#define CUBE(x) (x * x * x)
int main() {
printf("%d", CUBE(4+5));
return 0;
}
Yanıtlar
Makro, kodu şuna çevirecektir:
printf("%d", (4+5 * 4+5 * 4+5));
etkili olan:
printf("%d", 4 + (5*4) + (5*4) + 5); // 29
Küp 9
almak 729
istiyorsanız yazmalısınız CUBE((4+5))
.
Derleme işlemi sırasında makronun nasıl genişletildiği aşağıda açıklanmıştır:
printf("%d", (4+5 * 4+5 * 4+5));
Çünkü *
daha yüksek bir önceliğe sahip +
bu ifade olarak değerlendirilir (4 + (5 * 4) + (5 * 4) + 5)
üreten 49
yerine beklenen 729
.
Bu tür operatör öncelik sorunlarından kaçınmak için, tüm makro argümanlar makro tanımında ve ifadenin kendisinde parantez içine alınmalıdır:
#define CUBE(x) ((x) * (x) * (x))
Bununla birlikte, bu genişlemenin birden çok kez CUBE
değerlendirildiğini unutmayın; bu x
, makro bağımsız değişkeninin CUBE(i++)
.
Tüm bu sorunları önlemek için bir işlev kullanın ve derleyicinin onu optimize etmesine izin verin:
int cube(int x) {
return x * x * x;
}
static inline
Bu işlev tanımının önüne ekleyebilirsiniz , ancak modern eniyileyiciler bu olmadan işlevi yine de satır içi olacaktır.
C ön işlemcisi tam anlamıyla x'in tüm örneklerini 4 + 5 yerine koyacak ve sonuçta aşağıdaki kod ortaya çıkacaktır:
i = 4+5*4+5*4+5;
(önce çarpma, sonra toplama)
CUBE((4+5))
Numaraları eklemek ve sonra göndermek istiyormuş gibi girdi vermeniz gerekiyor CUBE
. Çünkü , yerine bütünü ayarladığı için CUBE(4+5)
, temelde genişletilir . Öyleyse, = çarpma önce gelir ve sonra onları toplamak verir .4+5*4+5*4+5
4+5
x
4+5*4+5*4+5
4+20+20+5
49
Makroyu #define CUBE(x) ((x)*(x)*(x))
gerçekte olduğu gibi tanımlayın, önce (4+5)
her biri için işlemi ilerletin (x)
ve sonra *
işlemi yapın.
Diğer bir yol ise sadece CUBE((4+5))
makroyu çağırırken kullanmaktır , temelde önce iki sayıyı ekledi ve (4+5)
= 9
ve sonra CUBE(9)
şöyle yapın:
#include<stdio.h>
#define CUBE(x) (x * x * x)
int main( )
{
printf("%d", CUBE((4+5)));
return 0;
}
Okuma Modern C , daha sonra n1570 taslak C standart ve dokümantasyonu GCC ve GDB ve cpp . Ayrıca bu C referans web sitesine bakın.
Github veya GNU yazılımı gibi mevcut açık kaynak projelerinden ilham alın .
Son ile GCC derleyicisi, onu çağırmak olarak gcc -Wall -Wextra -g
. Önceden -C -E
işlenmiş formu almak için seçenekleri de kullanın .
GCC'nin ifade-ifade uzantısı da ilginizi çekebilir .
Sizin CUBE(4+5)
makro genişletilmiş etmektir 4+5*4+5*4+5
olarak hesaplanır hangi 4+(5*4)+(5*4)+5
önceliğine göre C operatörleri .
Şunun static inline
gibi bir işlevi kodlamayı düşünün:
static inline int cube(int x) { return x*x*x; }
veya en azından bir makroya ihtiyacınız varsa
#define CUBE(X) ((X)*(X)*(X))
bunun için iyi çalışmaz CUBE(i++)
( inline
işlevle birlikte, cube(i++)
yapmasını istediğiniz şeyi yapar: bir i
kez artırın!).
BTW, bazı C kodu oluşturmak için GPP veya GNU m4'ü (veya kendi oluşturucunuzu veya GNU bizonunu ) kullanabilirsiniz. Genel bir kural olarak, AST s ile düşünün : C kodu oluşturduğunuzda, örneğin Chicken Scheme , SWIG veya CAIA veya benim manydl.c'de olduğu gibi, pek çok yararsız parantez kullanın.
Kodunuzda (ve belki Frama-C ) Clang statik analizcisini de kullanabilirsiniz .
MISRA C veya GNU gibi bazı kodlama yönergelerini okumak ilginizi çekebilir .