指向字面值的指针

假设我在头文件中定义了一个常量

#define THIS_CONST 'A' 

我想将此常量写入流。 我做的事情如下:

 char c = THIS_CONST; write(fd, &c, sizeof(c)) 

但是,为简洁明了,我想做的是:

 write(fd, &THIS_CONST, sizeof(char)); // error // lvalue required as unary '&' operand 

有谁知道获取指向文字的指针的任何宏/其他技巧? 我想要一些可以这样使用的东西:

 write(fd, PTR_TO(THIS_CONST), sizeof(char)) 

注意:我意识到我可以将我的常量声明为静态const变量,但是我不能在switch / case语句中使用它们。 即

 static const char THIS_CONST = 'A' ... switch(c) { case THIS_CONST: // error - case label does not reduce to an integer constant ... } 

除非有办法在案例标签中使用const变量?

在C89中无法直接执行此操作。 您必须使用一组宏来创建这样的表达式。

在C99中,允许声明struct-or-union文字,并且可以使用类似的语法编写标量的初始化器。 因此,有一种方法可以达到预期的效果:

 #include  void f(const int *i) { printf("%i\n", *i); } int main(void) { f(&(int){1}); return 0; } 

获取指针的唯一方法是将文字放入变量(第一个代码示例)。 然后,您可以将变量与write()switch的文字一起使用。

C根本不允许像’A’这样的字符文字地址。 对于它的价值,C中的字符文字类型是int(C ++中的char,但这个问题标记为C)。 ‘A’将具有实现定义的值(例如ASCII系统上的65)。 获取值的地址没有任何意义,也是不可能的。

现在,您当然可以使用其他类型的文字的地址,例如字符串文字,例如以下是可以的:

 write(fd, "potato", sizeof "potato"); 

这是因为字符串文字“potato”是一个数组,它的值是一个指向开头’p’的指针。

要详细说明/澄清,您只能获取对象的地址。 即,&(address-of)运算符需要一个对象,而不是一个值。

为了回答我错过的另一个问题,C不允许非常量的case标签,这包括声明为const的变量。

由于调用write()将单个字符写入文件描述符几乎肯定是性能杀手,因此您可能只想执行fputc(THIS_CONST,stream)。

 #define THIS_CONST 'a' 

只是一个宏。 编译器基本上只是在你使用THIS_CONST的地方插入’a’。 你可以尝试:

 const char THIS_CONST = 'a'; 

但是我怀疑它不会枯萎(没有一个c-compiler方便试试它,而且我已经写了很多年了,因为我编写了c代码)。

只需使用一个字符串常量,这是一个指向字符的指针,然后只写1个字节:

 #define MY_CONST_STRING "A" write(fd, MY_CONST_STRING, 1); 

请注意,不写入字符串末尾的’\ 0’字节。

您可以为各种常量值执行此操作,只需使用适当的hex代码字符串,例如

 #define MY_CONST_STRING "\x41" 

也将给出角色’A’。 对于多字节内容,请注意使用正确的字节顺序。

假设您想要一个指向INT_MAX的指针,例如在32位系统上为0x7FFFFFFF。 然后你可以做以下事情:

 #define PTR_TO_INT_MAX "\xFF\xFF\xFF\x7F" 

你可以通过将它作为一个解释引用指向printf来看到它的工作原理:

 printf ("max int value = %d\n", *(int*)PTR_TO_INT_MAX); 

其中应该打印2147483647。

这些答案都已过时,除了评论之外,没有人提到最近的语言更新。

在使用复合文字的C99-C11编译器http://en.cppreference.com/w/c/language/compound_literal上 ,可以创建指向无名常量的指针,如下所示:

 int *p = &((int){10}); 

对于字符,您可以使用额外的全局静态变量。 也许是这样的:

 #define THIS_CONST 'a' static char tmp; #define PTR_TO(X) ((tmp = X),&tmp) write(fd,PTR_TO(THIS_CONST),sizeof(char)); 

编译器没有理由将文字放入任何内存位置,所以你的问题没有意义。 例如一个声明

 int a; a = 10; 

可能只是直接翻译成“将值十放入寄存器”。 在编译器的汇编语言输出中,除了作为实际程序文本的一部分之外,值10本身甚至从未作为内存中可以指向的东西存在。

你不能指向它。

如果你真的想要一个宏来获取指针,

 #include  static char getapointer[1]; #define GETAPOINTER(x) &getapointer, getapointer[0] = x int main () { printf ("%d\n",GETAPOINTER('A')); } 

我可以看到你在这里尝试做什么,但你在这里试图使用两个根本不同的东西。 问题的关键在于case语句需要使用在编译时出现的值,但是指向内存中数据的指针仅在运行时可用。

当你这样做:

 #define THIS_CONST 'A' char c = THIS_CONST; write(fd, &c, sizeof(c)) 

你做了两件事。 您正在编译时将宏THIS_CONST用于其余代码,并且您在运行时创建一个初始化为此值的新char 。 在执行行write(fd, &c, sizeof(c))THIS_CONST的概念不再存在,因此您已正确识别可以创建指向c的指针,但不能创建指向THIS_CONST的指针。

现在,当你这样做时:static const char THIS_CONST =’A’; switch(c){case THIS_CONST:// error – case label不会减少为整数常量…}

您正在编写代码,其中case语句的值需要在编译时进行评估。 但是,在这种情况下,您已经以一种变量的方式指定了THIS_CONST ,因此它的值仅在运行时可用, 尽管您“知道”它将具有特定值 。 当然,其他语言允许使用case语句发生不同的事情,但那些是C语言的规则。

这是我的建议:

1)不要调用变量THIS_CONST 。 没有技术理由不这样做,但是惯例表明这是一个编译时宏,你不想让你的读者感到困惑。

2)如果希望在编译时和运行时可以使用相同的值,请找到将编译时宏映射到运行时变量的合适方法。 这可能很简单:

 #define CONST_STAR '*' #define CONST_NEWLINE '\n' static const char c_star CONST_STAR; static const char c_newline CONST_NEWLINE; 

然后你可以这样做:

 switch(c) { case CONST_STAR: ... write(fd, &c_star, sizeof(c_star)) ... } 

(另请注意,根据定义, sizeof(char) 总是一个。你可能已经知道了,但它并没有像它应该的那样被广泛认可。)

好吧,我已经提出了一些黑客攻击,仅限于字符 – 但我会把它放在这里,看看它是否能激发其他任何人更好的解决方案

 static const char *charptr(char c) { static char val[UCHAR_MAX + 1]; val[(unsigned char)c] = c; return &val[(unsigned char)c]; } ... write(fd, charptr(THIS_CONST), sizeof(char));