指向字面值的指针

时间:2009-10-14 07:09:44

标签: c

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

#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变量吗?

11 个答案:

答案 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));