Know if constant determinant is used

Is there a way in C to find if a variable has a const specifier? Or if it is stored in the .rodata section?

For example, if I have this function:

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

in these two different function calls, different actions must be performed:

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

In the first case, I can change the line, in the second - no.

+4
source share
4 answers

Not in the C standard, i.e. not portable.

myString is just a char* in foo , all other information is lost. Everything that you load into a function is automatically converted to char* .

And C does not know about " .rodata ".

Depending on your platform, you can check the address in myString (if you know the address ranges).

+4
source

GCC provides __builtin_constant_p built-in function that allows you to determine whether an expression is constant or not at compile time:

Built-in Function: int __builtin_constant_p (exp)

You can use the __builtin_constant_p built-in function to determine whether a value is known to be constant at compile time, and therefore, GCC can perform constant folding in expressions associated with that value. The argument of the function is the value to check. The function returns an integer 1 if it is known that the argument is a compile time constant and 0 if it is not known that it is a compile time constant. A return of 0 does not indicate that the value is not a constant, but simply that GCC cannot prove that it is a constant with the specified value of the -O option.

So, I think you should rewrite your foo function as a macro in this case:

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

foo("abc") will expand to foo_on_const("abc") , and foo(str) will expand to foo_on_var(str) .

+2
source

You cannot distinguish them using only one language. In other words, this is not possible without repeating functions specific to the compiler used, which is probably not portable. A few important points:

In the first case, you MAY change the line, but DO NOT. If you want a variable string, use initialization instead of assignment.

 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 
+2
source
 #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"); } 

When compiling with gcc -DCHECK prog_name.c and executing on my Linux machine, the following output appears ...

 strings address 0xbfdcacf6 local variables address 0xbfdcacc8 strings address 0x8048583 local variables address 0xbfdcacc8 strings address 0x8048583 local variables address 0xbfdcacc8 

for the first case, when a string is defined and initialized in the "correct path for mutable strings", the difference between the addresses is 0x2E (5 bytes).

in the second case, when the string is defined as char * p = "hi", the differences in the addresses are 0xB7D82745.Thats are larger than the size of my stack.so, I am sure that the string is not on the stack. This is the only place you can find the .rodata section.

The third example is similar to the case

PS: As mentioned above, this is not portable, but the original question hardly leaves room for portability by specifying .rodata strong> :)

+1
source

Source: https://habr.com/ru/post/1246994/


All Articles