I get lvalue required as increment operand error message with gcc-4.7 for
void func1()
{
u32 *src;
hwrcolor c;
c = *(((u32*)src)++);
}
and
void func2()
{
u8 *dest;
hwrcolor c;
u32 * u32Dest;
*(((u32 *)dest)++) = c;
}
I change them to
void func1()
{
u32 *src;
hwrcolor c;
u32Dest = ((u32*)src);
//c = *(u32Dest ++);
*u32Dest = *u32Dest + 1;
c = *u32Dest;
}
and
void func2()
{
u8 *dest;
hwrcolor c;
u32 * u32Dest;
u32Dest = ((u32 *)dest);
//*(u32Dest++) = c;
*u32Dest = *u32Dest + 1;
*u32Dest = c;
}
source code can be compiled but application not work as expected. Are conversions true?
The code:
((T *)p)++
is illegal because ++ may only be applied to an lvalue.
This is because the side-effect of ++ is to increment the value stored in a variable, but (T *)p isn't a variable; it's a temporary result of converting p to a new type.
This is the same sort of error as int x = 5; (x + 3)++; . It doesn't make sense.
In some older compilers, the code ((T *)p)++; was accepted and treated like:
(*(T **)&p)++;
In other words, the memory location storing p was treated as if it actually stored a pointer of another type, and then that pointer is incremented. This worked on those compilers because those compilers only ran on hardware where all pointers are stored in the same way.
The fix for your func1 is simply to write c = *src++; . No casts are necessary because src is already the right type.
In func2 the code *(((u32 *)dest)++) = c; could be replaced with:
*(*(u32 **)&dest)++ = c;
Your version doesn't work because you never increment the original dest. In fact in both of your attempts you increment the data being pointed to, whereas the original code increments the pointer, leaving the data untouched.
Note that func2 violates the strict aliasing rule. Older compilers did not optimize based on the strict aliasing rule, but recent versions of gcc do. You should use the flag -fno-strict-aliasing when compiling this code.
Related
int LCS_length(char* x, char* y)
{
int m = strlen(x);
int n = strlen(y);
char b[m + 1][n + 1];
char c[m + 1][n + 1];
}
In this code i want to declare a new two dimensional arrays, but my compiler write me this error:
Expression must have a constant value
Who knows what can i do, because a compiler don't let me do this statement in C language?
NOTE: it just part of the code and it has return statement later.
You must compile the code with a standard C compiler, such as gcc or clang etc. You can't compile using C++ compilers or non-C-compilers such as Microsoft VS.
Other than that, the code is fine apart from missing a return statement.
If you are stuck with old crap compilers, you can alternatively do an old style "mangled array":
size_t m = strlen(something) + 1;
size_t n = strlen(something) + 1;
...
char* b = malloc(m*n);
...
b[i*n + j] = something;
...
free(b);
That is how we used to allocate 2D arrays dynamically back in the old days.
Equivalent code using dynamic allocation in modern standard C would be:
char (*b)[n] = malloc( sizeof(char[m][n]));
...
b[i][j] = something;
...
free(b);
It looks that it wants a specific constant value like: char b[5][5];
Expression must have a constant value
C supports variable sized arrays from C99 standard. Maybe your compiler does not support Variable Length Arrays.
You can see more information at What's the point of VLA anyway?.
And may be helpful: Why aren't variable-length arrays part of the C++ standard?
You can use dynamically allocation instead (Unless you want each index to be a variable-length string, there is really no need for the char** trick: Correctly allocating multi-dimensional arrays):
char **b = malloc((m+1)*sizeof(char *));
if(b) {
for (int i = 0; i < m+1; i++0 {
b[i] = malloc(n+1);
if(!b[i]) {
// handle the error.
}
}
}
Or you can define the constant value MAX_ROW_LENGTH and MAX_COL_LENGTH:
#define MAX_ROW_LENGTH 100
#define MAX_COL_LENGTH 256
Then you can use:
char b[MAX_ROW_LENGTH][MAX_COL_LENGTH];
I have a question about strict-aliasing and clang optimizations for one example.
Let's consider the following example (1):
typedef void (*FTy)(void);
FTy F = 0;
(*F)();
It is an undefined behavior.
Let's consider the example (2) below:
typedef void (*FTy)(void);
static const FTy F = 0;
void g( int flag)
{
if ( flag )
{
(*F)();
}
}
int main( void)
{
g( 0);
return (0);
}
Indirect call by F is still "undefined behavior", but stands under always false condtion. So programm must be correct.
Now let's consider the main example (3):
(second edition: Thanks to #Antti Haapala simplified version)
(third edition: using of always_inline)
#include <stdio.h>
#ifndef BUGGY
#define BUGGY 1
#endif
static inline void __attribute__((always_inline)) longLongAssign( int cond, char *ptr)
{
if ( cond )
{
*((long long *)ptr) = 0;
}
}
void funcA(int s, int g)
{
int i, j = 0, k;
int grp[4] = {-1, -1};
void *ptr[2] = {(void *)&(grp[0]), 0};
for (i = 0, k = 0; i < 1; ++i) {
for (j = 0; j < 1; ++j) {
if ( grp[g] > 0 )
{
if ( g > 5 )
{
continue;
} else
{
longLongAssign( g > 3, (char *)ptr[0]);
}
}
grp[k++] = 0;
}
printf("this should be zero: %d\n", grp[0]);
}
}
int main(void) {
funcA(0, 1);
}
Compile by gcc and execute
this should be zero: 0
Compile by "clang-7.0 -O0" and execute
this should be zero: 0
Compile by "clang-7.0 -O1 -fno-strict-aliasing" and execute
this should be zero: 0
Compile by "clang-7.0 -O1" and execute
this should be zero: -1
In the main example one of stores to grp formally violates strict-aliasing
*((long long *)ptr) = 0;
But this store stands under always false condition.
The question here is: how a store operation
violating breaking strict-aliasing rule
but located in unreachable statement
may affect any way to program execution?
Is it correct by C language standart?
Is an example (4) below correct, well defined and hasn't undefined behavior?
void assign( int type, char *ptr)
{
if ( ptr )
{
if ( (type == 0) )
{
*((int *)ptr) = 1;
} else if ( (type == 1) )
{
*((float *)ptr) = 1;
} else
{
// unknown type
}
}
}
int main( void)
{
int a;
float b;
assign( 0, (char *)&a);
assign( 1, (char *)&b);
assign( 0, (char *)0);
return (0);
}
Inline and constant propagation optimizations in function main gives
...
if ( &a )
{
if ( (0 == 0) )
{
*((int *)&a) = 1;
} else if ( (0 == 1) )
{
*((float *)&a) = 1;
} else
{
// unknown type
}
}
...
In one hand store operation
*((float *)&a) = 1;
formally violates strict-aliasing, but stands in unreacheble location.
Which reasons example (4) may be incorrect?
If example (4) is correct so why example (3) gives by clang compilation different results?
The expression statement
*(long long *)grp = 0;
has undefined behavior on account of accessing an object of type int[4] via an lvalue of different, incompatible type (long long) -- a strict-aliasing violation, as you observe in the question. But that doesn't have to be limited to runtime behavior. The (potential) issue being visible at translation time, the translation-time behavior is undefined, too, and therefore so is the result of every execution.
Or at minimum, that's an interpretation of the standard to which at least some compiler developers subscribe. Some folks around here object to such interpretations, but that doesn't change the fact that you have to deal with them.
With regard to the update
Your example (4) has perfectly well-defined behavior. The major considerations here are
It is explicitly permitted to convert a value of one object-pointer type to a different object-pointer type. There are caveats about alignment of the result, but C requires it always to work for conversion to char *, and it requires the reverse conversion to reproduce the original pointer value (which has no alignment issue if it was valid to begin with).
It is permitted to access any object's representation via an lvalue of character type. In other words, a char * is permitted to alias any part of any object, so even though you don't access anything directly through the char * values passed to assign(), a conforming compiler must assume that those pointers could alias any object in the program.
A null pointer of any type can be converted to another object-pointer type, resulting in a null pointer of the target type.
By use of the type argument to function assign() in a manner consistent with that function's implementation, the program ensures that each object involved is ultimately accessed (only) via an lvalue of its correct type.
What optimizations the compiler might apply are irrelevant to this analysis. It is the code you present to the compiler by which behavior, if defined, is established. Supposing that the program has defined behavior, it is the compiler's responsibility to ensure that that behavior is exhibited by the program resulting from translation to an executable, and it may and does use its knowledge about its own implementation to provide for that.
Thank you all for your comments! You've helped me to understand the problem much better.
Just to clarify why I do this and what I really wanted:
I am porting clang on some specific platform. So my goal here was to understand if this test (from our autogen test system) contains error, or rather it's clang compilation bug. On results of this discussion, I've submitted an llvm bug
(https://bugs.llvm.org/show_bug.cgi?id=41178).
Thanks again!
I have the following code:
#define MIN(a,b) (a <= b ? a : b)
void main()
{
int a = 5;
int* p = &a;
int result = MIN(*p++,12);
printf("%i",result);
}
Theoretically the output should be something smaller than 12, but it turned out giving 34 as its result. So I'm wondering is there something wrong with that inline function or the pointer?
BTW, I meant to have *p++ there rather than (*p)++. I understand it's gonna increment the address and unbox it.
So another question is normally what could be the value of the next address? In this case, what is the value of *p++?
This line:
int result = MIN(*p++,12);
expands to:
int result = (*p++ <= 12 ? *p++ : 12);
^^^^ ^^^^
So p gets incremented twice, and the value returned is garbage (note that this is actually undefined behaviour).
And this is why the use of such macros is strongly discouraged - you really don't want nasty side-effects like this.
Use a proper inline function instead of a macro:
inline int MIN(int a, int b)
{
return a <= b ? a : b;
}
Platform: Linux 3.2.0 x86 (Debian Wheezy)
Compiler: GCC 4.7.2 (Debian 4.7.2-5)
I am writing a function that copies the contents of a buffer to another buffer. I use a void pointer so that the function is not type specific. I have a testable version and it appears that the function is working properly. But I do not know if what I am doing is legal so my question is what are the pitfalls of what I have done if there are any.
#include <stdio.h>
#include <stdlib.h>
void* voidcpy(void *void_ptr, size_t nbytes)
{
char *char_ptr = void_ptr;
char *cpy_char_ptr = NULL;
size_t i = 0;
if((cpy_char_ptr = malloc(nbytes)) == NULL) return NULL;
for(; i < nbytes; i++) cpy_char_ptr[i] = char_ptr[i];
return cpy_char_ptr;
}
int main()
{
short int *intp = NULL;
short int *cpy_intp = NULL;
size_t siz = 5;
int i = 0;
if((intp = malloc(siz * sizeof(short int))) == NULL)
{
perror("(malloc)");
return -1;
}
intp[0] = 0;
intp[1] = 14;
intp[2] = 187;
intp[3] = 12678;
intp[4] = -234;
if((cpy_intp = voidcpy(intp, siz * sizeof(short int))) == NULL)
return -2;
printf("intp = %p\ncpy_intp = %p\n\n", (void*)intp, (void*)cpy_intp);
for(; i < siz; i++) printf("cpy_intp = %i\n", cpy_intp[i]);
free(intp);
free(cpy_intp);
return 0;
}
Yes, this is perfectly legal, in C you can legally assign a void pointer to any other pointer type and you can assign any pointer type to a void pointer.
In C++ this is not allowed. In C++ you would have to use a reinterpret_cast to cast to a different pointer type because the free void pointer casting that is allowed in C is considered a "loop hole" that is easy to make mistakes with.
Of course there is a truth to that idea, if you're not careful you could be doing the wrong thing, e.g. you could easily pass a pointer to a pointer to this function by mistake and then your function will happily overwrite whatever is on the stack beyond that pointer. This is no fault of your implementation however, it's just the way the function is to be used and memcpy behaves no differently.
Nevertheless you would be better off using memcpy instead as this will very likely be much better optimized, though these days the compiler will probably make a pretty decent version out of your code as well.
A few more pointers;
1) you do not need to malloc the original array, you can initialize it statically like so
short int int_arr[] = {
0,
14,
187,
12678,
-234,
};
2) you can then call your function in the following way:
cpy_int_arr = voidcpy(int_arr, sizeof(int_arr));
3) if you don't want to define the array statically, then use the pointer to get the element size, that way you can change the array type without needing to change it somewhere else in the code, which reduces the potential dangers of the "loop hole" void casting:
cpy_intp = voidcpy(intp, siz * sizeof(*intp));
4) you don't need to cast to void* in the printf call
5) try to assign variables immediately and do not put assignments inside of if statements:
char *cpy_char_ptr = malloc(nbytes)
if (cpy_char_ptr == NULL)
return NULL;
6) similarly you can define a iteration variable inside the loop clause:
for(size_t i = 0; i < nbytes; i++) cpy_char_ptr[i] = char_ptr[i];
The reason to define variables as late as possible and initialize them immediately is that you keep the scope of the variables as small as possible and you can not mistakenly use a variable before it is initialized.
7) (personal preference) don't use type names in your identifiers (intp, voidcpy) your code will either become difficult to read/understand if your identifier states a type different from what the variable actually is, (e.g. your type is actually a short int and not an int as the variable name would suggest,) or you will need to change the identifier throughout the entire code whenever you change the type with the possibility of making mistakes.
This question already has answers here:
C function syntax, parameter types declared after parameter list
(7 answers)
Closed 2 years ago.
I stumpled upon a C code, where variables seem to be declared after the argument list of a function. I did not know that this was possible.
In the code, int r and int *a are declared right after the argument list of arr2int. How does this affect the local variables a and r of arr2int?
The actual reason why I want to understand the code is because if I let it run on my linux x86 a[1] = 1 at //MARKER when arr2int ist called the fist time.
But if I let it run ona an ARM-based omap4 dev board a[1]=0 and I dont know why there is a difference.
Could someone comment on this please?
long arr2int(a,r)
int r;
int *a;
{
int i;
long mul, result = 0, temp;
//MARKER
for (i=1; i<=r; i++) {
mul = 1;
temp = a[i]-1;
while (temp--)
mul = mul << 1;
result += mul;
}
return(result);
}
And the calling method:
void generateEncodingTable(){
register int i,j;
long temp;
int seed = 133757;
printf("\n[I] - Generating Encoding Table\n");
for (pattern = 0; pattern < 4096; pattern++) {
temp = pattern << 11; /* multiply information by X^{11} */
encoding_table[pattern] = temp + get_syndrome(temp);/* add redundancy */
}
decoding_table[0] = 0;
decoding_table[1] = 1;
temp = 1;
for (i=2; i<= 23; i++) {
temp *= 2;
decoding_table[get_syndrome(temp)] = temp;
}
a[1] = 1; a[2] = 2;
temp = arr2int(a,2);
decoding_table[get_syndrome(temp)] = temp;
for (i=1; i<253; i++) {
nextcomb(23,2,a);
temp = arr2int(a,2);
decoding_table[get_syndrome(temp)] = temp;
}
a[1] = 1; a[2] = 2; a[3] = 3;
temp = arr2int(a,3);
decoding_table[get_syndrome(temp)] = temp;
for (i=1; i<1771; i++) {
nextcomb(23,3,a);
temp = arr2int(a,3);
decoding_table[get_syndrome(temp)] = temp;
}
}
This is an old notation known as K & R (Kernighan & Ritchie, after Brian Kernighan and Dennis Ritchie) Notation for declaring the functions. If your compiler supports it, you can use it and it is same as declaring the function with ANSI notation.
As mention by others, this is an early style of function coding.
Following is a pitfall of that style. Be aware there is no type checking on passed parameters. It may explain your run time differences.
Say you declare a function
int foo(a,b,c);
All the compiler sees at that point is a function named "foo" taking 3 arguments and
returning an int. Thus usage checking is limited to that.
Let's assume sizeof(short) < sizeof(int) < sizeof(long) and the function is defined as
int foo(a,b,c)
int a;
long b;
int c;
{ /* code body */ }
Notice the following usage of foo
int d,e,f;
d = foo(1,2L,3);
e = foo((short)1,2L,3);
f = foo(1,2,3);
The first usages works fine, the right size integers are passed to foo.
The 2nd usages also works fine. The first argument is promoted to int size before the call, much like printf("%d", (short)2) promotes (short)2 to int before passing to printf().
The 3rd is a problem as the compiler does not know the second argument needs to be long. Thus the data passed to foo is not passed correctly. --> UB
This is an old C syntax. If your compiler can swallow it then it should work the same as if you have declared the functions the normal, ANSI way.
This is K&R C, i.e, the C language described by the first edition of The C Programming Language by Brian Kernighan and Dennis Ritchie. The second edition has turned to ANSI C(C89).
You shoul always use ANSI C style:
Rationale for International Standard - Programming Languages C 6.11.6 Function declarators
The characterization as obsolescent of the use ofthe “old style” function declarations and
definitions, that is, the traditional style not using prototypes, signals the Committee’s intent that the new prototype style should eventually replace the old style.
The gist of this case is that the new syntax addresses some of the most glaring weaknesses of the language defined in K&R, that the new style is superior to the old style on every count.
It is just a way of declaring types of function parameters:
void func (first_param, second_param)
int first_param;
int second_param;
{
// ...
}
is equal to
void func (int first_param, int second_param)
{
// ...
}