A puzzling example about the C keyword "restrict" - c

The example is taken from Wikipedia:
void updatePtrs(size_t *restrict ptrA, size_t *restrict ptrB, size_t *restrict val)
{
*ptrA += *val;
*ptrB += *val;
}
I call this function in the main():
int main(void)
{
size_t i = 10;
size_t j = 0;
updatePtrs(&i, &j, &i);
printf("i = %lu\n", i);
printf("j = %lu\n", j);
return 0;
}
The val pointer is not be loaded twice according to the Wikipedia's description, so the value of j should be 10, but it's 20 in fact.
Is my comprehension about this keyword not correct? Should I utilize some specific options of gcc?
Thanks in advance.

Your code causes undefined behaviour. restrict is a promise from you to the compiler that all of the pointer parameters point to different memory areas.
You break this promise by putting &i for two of the arguments.
(In fact, with restrict it is allowed to pass overlapping pointers, but only if no writes are done through any of the overlapping pointers within the function. But typically you would not bother with restrict if there is no writing happening).
FWIW, on my system with gcc 4.9.2, output is j = 20 at -O0 and j = 10 at -O1 or higher, which suggests that the compiler is indeed taking note of the restrict. Of course, since it is undefined behaviour, your results may vary.

Related

Clang strict-aliasing optimizations vs unreachable code violating strict-aliasing

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!

How to return multiple types from a function in C?

I have a function in C which calculates the mean of an array. Within the same loop, I am creating an array of t values. My current function returns the mean value. How can I modify this to return the t array also?
/* function returning the mean of an array */
double getMean(int arr[], int size) {
int i;
printf("\n");
float mean;
double sum = 0;
float t[size];/* this is static allocation */
for (i = 0; i < size; ++i) {
sum += arr[i];
t[i] = 10.5*(i) / (128.0 - 1.0);
//printf("%f\n",t[i]);
}
mean = sum/size;
return mean;
}
Thoughts:
Do I need to define a struct within the function? Does this work for type scalar and type array? Is there a cleaner way of doing this?
You can return only 1 object in a C function. So, if you can't choose, you'll have to make a structure to return your 2 values, something like :
typedef struct X{
double mean;
double *newArray;
} X;
BUT, in your case, you'll also need to dynamically allocate the t by using malloc otherwise, the returned array will be lost in stack.
Another way, would be to let the caller allocate the new array, and pass it to you as a pointer, this way, you will still return only the mean, and fill the given array with your computed values.
The most common approach for something like this is letting the caller provide storage for the values you want to return. You could just make t another parameter to your function for that:
double getMean(double *t, const int *arr, size_t size) {
double sum = 0;
for (size_t i = 0; i < size; ++i) {
sum += arr[i];
t[i] = 10.5*(i) / (128.0 - 1.0);
}
return sum/size;
}
This snippet also improves on some other aspects:
Don't use float, especially not when you intend to return a double. float has very poor precision
Use size_t for object sizes. While int often works, size_t is guaranteed to hold any possible object size and is the safe choice
Don't mix output in functions calculating something (just a stylistic advice)
Declare variables close to where they are used first (another stylistic advice)
This is somewhat opinionated, but I changed your signature to make it explicit the function is passed pointers to arrays, not arrays. It's impossible to pass an array in C, therefore a parameter with an array type is automatically adjusted to the corresponding pointer type anyways.
As you don't intend to modify what arr points to, make it explicit by adding a const. This helps for example the compiler to catch errors if you accidentally attempt to modify this array.
You would call this code e.g. like this:
int numbers[] = {1, 2, 3, 4, 5};
double foo[5];
double mean = getMean(foo, numbers, 5);
instead of the magic number 5, you could write e.g. sizeof numbers / sizeof *numbers.
Another approach is to dynamically allocate the array with malloc() inside your function, but this requires the caller to free() it later. Which approach is more suitable depends on the rest of your program.
Following the advice suggested by #FelixPalmen is probably the best choice. But, if there is a maximum array size that can be expected, it is also possible to wrap arrays in a struct, without needing dynamic allocation. This allows code to create new structs without the need for deallocation.
A mean_array structure can be created in the get_mean() function, assigned the correct values, and returned to the calling function. The calling function only needs to provide a mean_array structure to receive the returned value.
#include <stdio.h>
#include <assert.h>
#define MAX_ARR 100
struct mean_array {
double mean;
double array[MAX_ARR];
size_t num_elems;
};
struct mean_array get_mean(int arr[], size_t arr_sz);
int main(void)
{
int my_arr[] = { 1, 2, 3, 4, 5 };
struct mean_array result = get_mean(my_arr, sizeof my_arr / sizeof *my_arr);
printf("mean: %f\n", result.mean);
for (size_t i = 0; i < result.num_elems; i++) {
printf("%8.5f", result.array[i]);
}
putchar('\n');
return 0;
}
struct mean_array get_mean(int arr[], size_t arr_sz)
{
assert(arr_sz <= MAX_ARR);
struct mean_array res = { .num_elems = arr_sz };
double sum = 0;
for (size_t i = 0; i < arr_sz; i++) {
sum += arr[i];
res.array[i] = 10.5 * i / (128.0 - 1.0);
}
res.mean = sum / arr_sz;
return res;
}
Program output:
mean: 3.000000
0.00000 0.08268 0.16535 0.24803 0.33071
In answer to a couple of questions asked by OP in the comments:
size_t is the correct type to use for array indices, since it is guaranteed to be able to hold any array index. You can often get away with int instead; be careful with this, though, since accessing, or even forming a pointer to, the location one before the first element of an array leads to undefined behavior. In general, array indices should be non-negative. Further, size_t may be a wider type than int in some implementations; size_t is guaranteed to hold any array index, but there is no such guarantee for int.
Concerning the for loop syntax used here, e.g., for (size_t i = 0; i < sz; i++) {}: here i is declared with loop scope. That is, the lifetime of i ends when the loop body is exited. This has been possible since C99. It is good practice to limit variable scopes when possible. I default to this so that I must actively choose to make loop variables available outside of loop bodies.
If the loop-scoped variables or size_t types are causing compilation errors, I suspect that you may be compiling in C89 mode. Both of these features were introduced in C99.If you are using gcc, older versions (for example, gcc 4.x, I believe) default to C89. You can compile with gcc -std=c99 or gcc -std=c11 to use a more recent language standard. I would recommend at least enabling warnings with: gcc -std=c99 -Wall -Wextra to catch many problems at compilation time. If you are working in Windows, you may also have similar difficulties. As I understand it, MSVC is C89 compliant, but has limited support for later C language standards.

Convert a non-pointer variable to a pointer to an array

Ok, I understand that my title might be a bit confusing, but I'll explain. I'm working on a homework assignment in C. I'm given a .c file and need to come up with implementations for some functions.
In short, I have this as a .c file
typedef int set_t;
...
void init(set_t *a, int N); // Initialized an array to a of size N
...
int main() {
set_t a;
init(&a, 10);
}
In a couple of implementations I've come up with, I was able to create an array using a, but I keep getting segmentation faults when the program runs :-/. Is there away to initialize a as an array without changing anything in the original .c file except for the implementation of init(set_t *a, int N)?
EDIT
Here's my current implementation of init --> it leads to a segmentation fault
void init(set_t *a, int N) {
//set_t thing[10];
*a = malloc(sizeof(set_t)*N);
for (int i = 0; i < N; i++) {
*(a + i) = i;
}
printf("value of a[2] = %d\n", a[2]);
}
As things currently stand, the requirements imposed on you are wholly unreasonable. If you are building for 32-bit only, so sizeof(int) == sizeof(int *), then you can use brutal casting to get around the constraints. The code will not work on a 64-bit machine, though (unless sizeof(int) == sizeof(int *), which isn't the case on any machine I can immediately think of.
So, the brute force and casting technique is:
void init(set_t *a, int N)
{
assert(sizeof(set_t) == sizeof(set_t *)); // Ick, but necessary!
set_t *base = malloc(sizeof(set_t)*N);
if (base == 0)
*a = 0;
else
{
*a = (int)base; // Brutal; non-portable; stupid; necessary by the rules given!
for (int i = 0; i < N; i++) {
base[i] = i;
printf("value of a[2] = %d\n", base[2]);
printf("value of a[2] = %d\n", ((int *)*a)[2]); // Brutal and stupid too
}
}
Further, in the code in main(), you'll have to use ((int *)a) to make the type usable for dereferencing, etc. Without knowing about what is actually in that other code, it is impossible to be confident that anything will work. It might, but it probably won't.
At this stage, this looks like someone criminally misleading innocent novice programmers. This is not the way it should be coded at all. However, if that's what the doctor (professor) orders, then that's what you've got to do. But it is a mockery of good coding practices AFAICS and AFAIAC.
Professor realized that he had made an error in the assignment and fixed it. Changed set_t a to set_a *a.
Thanks for all your help (hope I didn't cause too many headaches!

How can I use variable number of parameters to function

I have this:
long int addsquares(int n, ...)
How can I access the parameters?
I can't use va_start and va_arg...
Implementation dependent...
pre test
long int addsquares(int n, int d1, ...){
printf("%p,%p\n", &n, &d1);
return 0L;
}
result :
windows 64bit system, vc10 (sizeof int:4)
003DFD54,003DFD58
windows 64bit system, gcc 4.4.3 (sizeof int:4)
000000000022FE60,000000000022FE68
for vc10:
long int addsquares(int n, ...){
int i, *p = &n;
long sum = 0L;
for(i=1;i<=n;++i)
sum += p[i]*p[i];
return sum;
}
for gcc:
long int addsquares(int n, ...){
int i, *p = &n;
long sum = 0L;
for(i=1;i<=n;++i)
sum += p[i*2]*p[i*2];
return sum;
}
If you are saying that you have a variadic function, and you're not allowed to use the variable argument macros (va_xxx) then you'd have to rewrite the content of those macro's yourself.
Unless you can change the function prototype, but I'm guessing that's now allowed either.
Use Arrays and store each parameter in one "cell" of the array.
long int addsquares(int[] parameters)
{
for (int i = 0; i < parameters.length(); i++)
{
//Use current parameter: parameters[i]
}
}
It's c# code, but i thinkit will work for c as well.
Check out the discussion in this thread... How does the C compiler implement functions with Variable numbers of arguments?
I think you'll find it gets you going in the right direction. Pay particular attention to the discussion on the need to use one of the arguments as a means to sort out what and where the other arguments are.

How can one make Clang optimize away useless array copies

Consider the following C99 code (that uses the alloca extension.)
void print_int_list(size_t size, int x[size]) {
int y[size];
memcpy(y, x, size * sizeof *x);
for (size_t ii = 0; ii < size; ++ii)
printf("%i ", y[ii]);
printf("\n");
}
void print_int_list_2(size_t size, int x[size]) {
for (size_t ii = 0; ii < size; ++ii)
printf("%i ", x[ii]);
printf("\n");
}
void print_int(int x) {
int * restrict const y = alloca(sizeof x);
memcpy(y, &x, sizeof x);
printf("%d\n", *y);
}
void print_int_2(int x) {
printf("%d\n", *x);
}
In the code print_int is optimized to be exactly the same as print_int_2 on Clang version 3.0 but the function print_int_list is not optimized away to print_int_2. Instead the useless array copy is kept.
This sort of thing is not a problem for most people but it is for me. I intend to prototype a compiler by generating C code for use with Clang, (and later port it to LLVM directly), and I want to generate extremely stupid, simple, and obviously correct code, and let LLVM do the work of optimizing the code.
What I need to know is how one can make Clang optimize away useless array copies so that stupid code like print_int_list will get optimized into code like print_int_list_2.
First, I would go more carefully. There is a step inbetween the two cases that you have, arrays of fixed size. I think nowadays compilers can trace array components that are also indexed with a compile time constant.
Also don't forget that memcpy converts your arrays to pointers to the first element and then makes them void*. So it looses all information.
So I'd go
try fixed sized arrays
don't use memcpy but an assignment loop
and try to losen the constraints from there.

Resources