假设我在头文件中定义了一个常量
#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变量吗?
答案 0 :(得分:30)
在C89中无法直接执行此操作。您必须使用一组宏来创建这样的表达式。
在C99中,允许声明struct-or-union文字,并且可以使用类似的语法编写标量的初始化器。因此,有一种方法可以达到预期的效果:
#include <stdio.h>
void f(const int *i) {
printf("%i\n", *i);
}
int main(void) {
f(&(int){1});
return 0;
}
答案 1 :(得分:5)
获取指针的唯一方法是将文字放入变量(第一个代码示例)。然后,您可以将变量与write()
和switch
中的文字一起使用。
答案 2 :(得分:4)
C根本不允许像'A'这样的字符文字地址。对于它的价值,C中的字符文字类型是int(C ++中的char,但这个问题标记为C)。 'A'将具有实现定义的值(例如ASCII系统上的65)。取一个值的地址没有任何意义,也是不可能的。
现在,当然你可能获取其他类型文字的地址,例如字符串文字,例如以下是可以的:
write(fd, "potato", sizeof "potato");
这是因为字符串文字“potato”是一个数组,它的值是一个指向开头的'p'的指针。
要详细说明,您只能获取对象的地址。即&amp; (address-of)运算符需要一个对象,而不是一个值。
为了回答我错过的另一个问题,C不允许非常量的case标签,这包括声明为const的变量。
答案 3 :(得分:3)
由于调用write()将单个字符写入文件描述符几乎肯定是一个性能杀手,你可能只想做fputc(THIS_CONST,stream)。
答案 4 :(得分:3)
#define THIS_CONST 'a'
只是一个宏。编译器基本上只是在你使用THIS_CONST的地方插入'a'。 你可以尝试:
const char THIS_CONST = 'a';
但是我怀疑它不会枯萎(没有一个c编译器可以试用它,而且自从我编写c代码以来已经有好几年了。)
答案 5 :(得分:2)
只使用一个字符串常量,它是一个指向字符的指针,然后只写1个字节:
#define MY_CONST_STRING "A"
write(fd, MY_CONST_STRING, 1);
请注意,不会写入字符串末尾的'\ 0'字节。
您可以对各种常量值执行此操作,只需使用适当的十六进制代码字符串,例如
#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。
答案 6 :(得分:2)
这些答案都已过时,除了评论之外,没有人提到最近的语言更新。
在C99-C11编译器上使用复合文字http://en.cppreference.com/w/c/language/compound_literal,可以创建 指向无名常量的指针,如:
int *p = &((int){10});
答案 7 :(得分:1)
对于字符,您可以使用额外的全局静态变量。也许是这样的:
#define THIS_CONST 'a'
static char tmp;
#define PTR_TO(X) ((tmp = X),&tmp)
write(fd,PTR_TO(THIS_CONST),sizeof(char));
答案 8 :(得分:0)
编译器没有理由将文字放入任何内存位置,所以你的问题没有意义。例如,像
这样的陈述int a;
a = 10;
可能只是直接翻译成“将值十放入寄存器”。在编译器的汇编语言输出中,除了作为实际程序文本的一部分之外,值10本身甚至从未作为内存中可以指向的东西存在。
你不能指向它。
如果你真的想要一个宏来获取指针,
#include <stdio.h>
static char getapointer[1];
#define GETAPOINTER(x) &getapointer, getapointer[0] = x
int main ()
{
printf ("%d\n",GETAPOINTER('A'));
}
答案 9 :(得分:0)
我可以看到你在这里尝试做什么,但你试图在这里使用两个根本不同的东西。问题的关键是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'; 开关(c){ case THIS_CONST://错误 - 大小写标签不会减少为整数常量 ... }
您正在编写代码,其中case语句的值需要在编译时进行评估。但是,在这种情况下,您以一种变量的方式指定了THIS_CONST
,因此它的值仅在运行时可用,尽管您“知道”它将具有特定值< / em>的。当然,其他语言允许使用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)
总是一个。您可能已经知道了,但它并没有得到应有的广泛认可。)
答案 10 :(得分:-2)
好吧,我已经提出了一些黑客攻击,仅限于字符 - 但我会把它放在这里,看看它是否能激发其他任何人更好的解决方案
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));