How to let gcc actually allocate variables instead substituting with symbols? - gcc

I noticed that if I have variables defined as char a = 'a'; or char a; a = 'a'; or even char a; a = 'a'; a = 'b';, and I try to do print a in gdb, it tells me No symbol "a" in current context.. Apparently gcc, during compilation, optimizes a to be a character constant, instead of a char variable holding a certain value.
How do I tell gcc not to do this trick, but really treat a as a variable (allocate memory and assign the character value to its memory)?

Related

Is ZeroMemory the windows equivalent of null terminating a buffer?

For example I by convention null terminate a buffer (set buffer equal to zero) the following way, example 1:
char buffer[1024] = {0};
And with the windows.h library we can call ZeroMemory, example 2:
char buffer[1024];
ZeroMemory(buffer, sizeof(buffer));
According to the documentation provided by microsoft: ZeroMemory Fills a block of memory with zeros. I want to be accurate in my windows application so I thought what better place to ask than stack overflow.
Are these two examples equivalent in logic?
Yes, the two codes are equivalent. The entire array is filled with zeros in both cases.
In the case of char buffer[1024] = {0};, you are explicitly setting only the first char element to 0, and then the compiler implicitly value-initializes the remaining 1023 char elements to 0 for you.
In C++11 and later, you can omit that first element value:
char buffer[1024] = {};
char buffer[1024]{};

passing argument 1 of 'strlen' makes pointer from integer without a cast

It is not clear why I get a warning of:
[Warning] passing argument 1 of 'strlen' makes pointer from integer without a cast [enabled by default]
expected 'const char *' but argument is of type 'char'
on two of the 3 statements containing strlen() below.
Even when I attempted to cast *str it still gave the same warning.
bfr is a character buffer. *str points to that char buffer after the call to
gets(). If I use strlen(*str) I get a warning. If I use strlen(bfr) I do not.
But *str should be the equivalent to bfr. Thus the confusion regarding the error.
Now in reality, strlen arg 1 is defined as strlen(const char *string). So I
would have expected strlen(bfr) to also produce an error since bfr[] is a
char string and not a const char either.
And where is the integer that is being made into a pointer?
I am using gcc under wXDev-C++.
void test(){
FILE *fileID = fopen("somefile.txt","r");
char *str, len;
char bfr[16];
str = fgets(bfr,16,fileID); // str will be set equal to &bfr[0]
len = strlen(*str); // This gives a warning
len = strlen((const char)*str); // This gives a warning
len = strlen(bfr); // This does not give a warning
}
Sometimes you just need to take a fresh look in the morning at a problem. I realized that strlen is looking for a pointer to a string and 'str' is defined as a pointer. So *str would be a pointer to a pointer. So the warning was correct. It should read len = strlen(s) not len = strlen(*s). And it is 'str' pointing to 'bfr' not *str;
Answered my own question.

changing the alignment requirement while casting

I get the warning " cast increases required alignment of target type" while compiling the following code for ARM.
char data[2] = "aa";
int *ptr = (int *)(data);
I understand that the alignment requirement for char is 1 byte and that of int is 4 bytes and hence the warning.
I tried to change the alignment of char by using the aligned attribute.
char data[2] __attribute__((aligned (4)));
memcpy(data, "aa", 2);
int *ptr = (int *)(data);
But the warning doesn't go away.
My questions are
Why doesn't the warning go away?
As ARM generates hardware exception for misaligned accesses, I want to make sure that alignment issues don't occur. Is there any other way to write this code so that the alignment issue won't arise?
By the way, when I print alignof(data), it prints 4 which means the alignment of data is changed.
I'm using gcc version 4.4.1. Is it possible that the gcc would give the warning even if the aligned was changed using aligned attribute?
I don't quite understand why you would want to do this... but the problem is that the string literal "aa" isn't stored at an aligned address. The compiler likely optimized away the variable data entirely, and therefore only sees the code as int* ptr = (int*)"aa"; and then give the misalignment warning. No amount of fiddling with the data variable will change how the literal "aa" is aligned.
To avoid the literal being allocated on a misaligned address, you would have to tweak around with how string literals are stored in the compiler settings, which is probably not a very good idea.
Also note that it doesn't make sense to have a pointer to non-constant data pointing at a string literal.
So your code is nonsense. If you still for reasons unknown insist of having an int pointer to a string literal, I'd do some kind of work-around, for example like this:
typedef union
{
char arr[3];
int dummy;
} data_t;
const data_t my_literal = { .arr="aa" };
const int* strange_pointer = (const int*)&my_literal;

What is "isra" in the kernel thread dump

Linux kernel call stack dump often includes function names that ends with ".isra.NNN" where NNN is some numbers. For example, see here and here.
What does that mean, what does the number signify?
isra is the suffix added to the function name when gcc option -fipa-sra compiler optimization being carried out.
From gcc manual:
-fipa-sra
Perform interprocedural scalar replacement of aggregates, removal of unused
parameters and replacement of parameters passed by reference by parameters passed
by value.
Enabled at levels -O2, -O3 and -Os.
All functions that are optimized under this option have isra appended to their names. I digged into gcc code and found out the function that was appending the string.
tree
clone_function_name (tree decl, const char *suffix)
{
tree name = DECL_ASSEMBLER_NAME (decl);
size_t len = IDENTIFIER_LENGTH (name);
char *tmp_name, *prefix;
prefix = XALLOCAVEC (char, len + strlen (suffix) + 2);
memcpy (prefix, IDENTIFIER_POINTER (name), len);
strcpy (prefix + len + 1, suffix);
#ifndef NO_DOT_IN_LABEL
prefix[len] = '.';
#elif !defined NO_DOLLAR_IN_LABEL
prefix[len] = '$';
#else
prefix[len] = '_';
#endif
ASM_FORMAT_PRIVATE_NAME (tmp_name, prefix, clone_fn_id_num++);
return get_identifier (tmp_name);
}
Here, argument 2, const char *suffix, is "isra" and notice at the bottom of the function macro ASM_FORMAT_PRIVATE_NAME which takes clone_fn_id_num++ as its 3rd argument. This is the arbitrary number found after "isra". This going by its name is the count of functions that are cloned under this compiler option (or may be a global counter that keeps track of all cloned functions).
If you want to understand more, search for modify_function in file gcc/tree-sra.c which in turn calls cgraph_function_versioning() which passes "isra" as its last argument.

charlower with gcc

I am trying to convert the following code from msvc to gcc
#define ltolower(ch) CharLower((LPSTR)(UCHAR)(ch))
char * aStr;
* aStr = (char)ltolower(*aStr);
This code is giving a compiler error: cast from ‘CHAR*’ to ‘char’ loses precision
My understanding is that tolower(int) from c wouldn't convert the whole string.
Thanks.
Your cast in CharLower is raising that error. Before doing that, you need to set the high order byte of the pointer passed to CharLower equals to ZERO.
From MSDN reference on the function:
If the operand is a character string,
the function returns a pointer to the
converted string. Because the string
is converted in place, the return
value is equal to lpsz.
If the operand is a single character,
the return value is a 32-bit value
whose high-order word is zero, and
low-order word contains the converted
character.
Something like this might work:
#define ltolower(ch) CharLower(0x00ff & ch)
If you are using a C++ compiler, you might also need a CAST operator:
#define ltolower(ch) CharLower((LPTSTR)(0x00ff & ch))
Haven't tested it though...

Resources