知道是否使用了const限定符

时间:2011-11-16 11:50:05

标签: c const

C中是否有任何方法可以查找变量是否具有const限定符?或者它是否存储在.rodata部分?

例如,如果我有这个功能:

void foo(char* myString) {...}

在这两个不同的函数调用中应采取不同的操作:

char str[] = "abc";
foo(str);

foo("def");

在第一种情况下,我可以修改字符串,在第二种情况下编号

4 个答案:

答案 0 :(得分:4)

不在标准C中,即不可移植。

myString只是char*中的foo,所有其他信息都会丢失。无论您输入函数的是什么,都会自动转换为char*

C不知道“.rodata”。

根据您的平台,您可以在myString中查看地址(如果您知道地址范围)。

答案 1 :(得分:2)

GCC提供__builtin_constant_p内置函数,使您能够在编译时确定表达式是否为常量:

  

内置函数:int __builtin_constant_p(exp)

     

您可以使用内置函数__builtin_constant_p来确定某个值是否在编译时是常量的,因此GCC可以对涉及该值的表达式执行常量折叠。函数的参数是要测试的值。如果已知参数是编译时常量,则函数返回整数1;如果不知道它是编译时常量,则返回0。返回0并不表示该值不是常量,而仅仅是GCC不能证明它是具有指定的“-O”选项值的常量。

所以我猜你应该在这种情况下将你的foo函数重写为宏:

#define foo(x) \
  (__builtin_constant_p(x) ? foo_on_const(x) : foo_on_var(x))

foo("abc")会扩展为foo_on_const("abc")foo(str)会扩展为foo_on_var(str)

答案 2 :(得分:2)

你不能仅仅使用这种语言来区分它们。换句话说,如果不重复使用特定于您正在使用的编译器的功能,这是不可能的,这可能不是可移植的。但是有一些重要的评论:

在第一种情况下,你可以修改字符串,但你不能。如果您想要一个可变字符串,请使用初始化而不是赋值

char *str1 = "abc"; // NOT OK, should be const char *
const char *str2 = "abc"; // OK, but not mutable
char str3[] = "abc"; // OK, using initialization, you can change its contents

答案 3 :(得分:2)

#include<stdio.h>
void foo(char *mystr)
{
int a;
/*code goes here*/   


#ifdef CHECK
int local_var;
printf(" strings address %p\n",mystr);
printf("local variables address %p \n",&local_var);
puts("");
puts("");
#endif
return;
}
int main()
{
char a[]="hello";
char *b="hello";
foo(a);
foo(b);
foo("hello");
}

在使用gcc -DCHECK prog_name.c进行编译并在我的linux机器上执行以下输出时......

strings address 0xbfdcacf6
local variables address 0xbfdcacc8 


strings address 0x8048583
local variables address 0xbfdcacc8 


strings address 0x8048583
local variables address 0xbfdcacc8 

对于第一种情况,当字符串被定义并以“适当的c方式为可变字符串”初始化时,地址之间的差异为0x2E。(5字节)。

在第二种情况下,当字符串被定义为char * p =“hello”时,地址的差异是 0xB7D82745.Thats大于我的堆栈的大小。所以我很确定字符串不在堆栈上。因为唯一可以找到它的地方是.rodata部分。

第三个是类似案例

PS:如上所述,这不是可移植的,但是原始问题通过提及 .rodata ,几乎没有留下任何可移植性的范围:)