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!
Related
I made a function for adding next numbers in the array. Code is very simple, like following
int math(int *address, int size)
{
int sum = 0;
for (int i = 0; i < size; i++)
{
sum += *address;
address++;
}
return sum;
}
During static analysis I found, that there is problem against MISRA rule - which is saying that you can do math only on pointers assigned to an array. Purpose of this function is to use it on arrays, but of course - what I wrote in here is not guarantee that pointer won't be assigned to a variable.
One work-around which I think about is to copy whole table to local area and then sum all elements, but it's rather big operation, wasting lot of uprocessors assets. Do you have any ideas how can I make it better?
This would be from MISRA-C:2004 chapter 17, which was rather irrational about the use of pointers and arrays. This chapter was rewritten from scratch in MISRA-C:2012 (chapter 18). I would strongly recommend to upgrade, since MISRA-C:2004 simply doesn't make much sense here.
As for how to make your code MISRA-C:2004 compliant, do this:
int math(int address[], int size)
{
int sum = 0;
int i; // declaration must be here, MISRA-C:2004 does not allow C99
for (i = 0; i < size; i++)
{
sum += address[i];
}
return sum;
}
Yes it does the very same thing. But at least it made your code slightly more readable.
To make your code even safer, although not compliant with any MISRA, do this:
// better than MISRA-C but not compliant
int math(size_t size, int address[size])
{
int sum = 0;
for (size_t i = 0; i < size; i++)
{
sum += address[i];
}
return sum;
}
Or in case of high integrity systems, you could even do:
int math(size_t size, int (*array)[size])
{
int* address = *array;
...
Both of these alternatives give safer code than MISRA-C.
In the code which follows, I keep getting an error. How to modify the third line? Why's that keep happening? What's wrong?
#include <stdio.h>
#include "stdlib.h"
#define ARRAY_IDX(type, array, i) ((type *)(array+i)) // you can only modify this line!
int main(int argc, const char * argv[]) {
void *ptr = malloc(10*sizeof(int));
#ifdef ARRAY_IDX
for (int i = 0; i < 10; i++) {
ARRAY_IDX(int, ptr, i) = i * 2;
}
for (int i = 0; i < 10; i++) {
printf("%d ", ARRAY_IDX(int, ptr, i));
}
free(ptr);
#else
printf("Implement ARRAY_IDX first");
#endif
}
Looking at
ARRAY_IDX(int, ptr, i) = i * 2;
and
printf("%d ", ARRAY_IDX(int, ptr, i));
shows that the expression
ARRAY_IDX(int, whatever, whatever)
should expand into an expression of type int (and an lvalue, so that we can assign to it).
Starting off with a void * you first need to change (cast) it to a pointer that allows indexing, and since you want to index the elements of that array (not its individual bytes, which would be a violation of aliasing) you need to make it an int * first:
(int *)(ptr)
Now you have a pointer to an integer (array, hopefully). Increment it:
(int *)(ptr) + (idx)
Finally, you need an lvalue int expression. Dereference the pointer to get that:
(*((int *)(ptr) + (idx)))
Converting that to a preprocessor macro is something that should be doable, so I leave it up to you.
Note that whoever is giving you that code is - IMHO - not a teacher you should trust. This won't teach you much about correct C. It might teach you something about the preprocessor. But don't write such code. Just don't. Use correct types if possible. Check for failure of malloc.
There is nothing wrong with adding an int to a void pointer. For many years, compiler designers assumed that this was standard behavior, and it was implemented as such. It's every bit as standard as anonymous structs and unions, which compilers have had for almost 20 years and were only recently added in C11. Practically all compilers will compile this just fine without any warnings or errors, and without having to use any special compiler flags.
Your problem is, as I have pointed out, that you are assigning a value to a pointer. You need to dereference it after the cast.
#define ARRAY_IDX(type, array, i) ((type *)array)[i]
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
pointer arithmetic in C for getting a string
I am a newbie in C and I would like to get the elements of an array with a function, I have tried different options, but I still do not get the elements.
My function is:
void getelements(int *a, int cl)
{
int *p;
for (p=&a[0];p<&a[cl];p++)
{
printf("%d\n",*p);
}
}
I know that the solution should work like that, but it only prints the first element and then memory positions. I am calling my function with:
int v={10,12,20,34,45};
getelements(&v,5);
Any help? I need to use arithmetic of pointers.
Thanks
First, Please don't update code to fix bugs while a question is open. It makes most of the current answers meaningless, doesn't grant credit where it is due to the person(s) that solved one or more issues in your prior code, and makes the casual reader looking for a related problem to their own completely confused by both the question and the answers therein. If you want to amend an update do so in addition to the original problem, but if it an entirely different issue, then mark as answered, give credit where it is due, and open a new question with your new code and different problem(s) (ideally, anyway).
As written now, your function is fine. But your real issue is this:
// compile with -Wall -Werror and look at the warning here
int v={10,12,20,34,45}; // <== WRONG
getelements(&v,5); // <== Harmless, but bad form.
This should be like this instead, assuming you want to print all elements in the array:
int v[] = {10,12,20,34,45};
getelements(v, sizeof(v)/sizeof(v[0]));
Note the [] following your array. Without it, the &v was masking what would have been a big-fat warning or error from the compiler that int is being passed as an int *. Furthermore, if you compile your prior code with full warnings treated as errors (-Wall -Werror for gcc) you will get an error like the following on your v declaration line:
main.c:116:15: Excess elements in scalar initializer
In other words, everything past the first element was ignored, and thus your pointer was running off into undefined behavior land. Changing the declaration and invocation to what I have above will address this as well as ensure you don't make that mistake again, since sizeof(v[0]) won't even compile unless v is an array or pointer type. The latter can still cause headaches when you use a pointer rather than an array with such a calculation, but thats something you just have to discipline yourself against doing in C.
try this and let me know if that works.
void getelements(int *a)
{
int *p;
int l=5;
for (p=a;p<a+l;p++)
{
printf("%d\n",*p);
}
}
It's best to pass in the length of the array along with the array itself.
#include <stdlib.h>
#include <stdio.h>
void get_elements(int* values, int length)
{
int i;
for (i = 0; i < length; ++i)
{
printf("%d\n", values[i]);
}
}
int main(int argc, char** argv)
{
int vals[3];
vals[0] = 0;
vals[1] = 1;
vals[2] = 2;
get_elements(vals, 3);
getchar();
return 0;
}
Using the code similar to your original post (before the addition of the array length as a method parameter), you could do the follow (which is a bit convoluted if you ask me).
void get_elements(int* values, int length)
{
int *p;
for (p = &values[0]; p < &values[length]; p++)
{
printf("%d\n", *p);
}
}
Actually you are passing array address in
getelements(&v,5)
in function
getelements()
you are treating it like an array!!!
void getelements(int *a, int cl)
{
int *p;
for (p=a;p<a+cl;p++)
{
printf("%d\n",*p);
}
}
Let me know if you are cleared conceptually!!!
As per my knowledge and seeing your code.you have hardcoded the length of array to 5. I think you can also pass array length as a parameter to function; or you can use this function and see if it gives the desired result
void getelements(int *a)
{
int *p;
int i = 0;
int l=5;
p = a
for (i = 0;i<l;i++)
{
printf("%d\n",*(p + i));
}
}
I must have tried 20 ways of doing this by now. I really need help, no matter what I do i get a error similar to this one.
a value of type "int" cannot be used to initialize an entity of type "int (*)[30]"
i.e. this will get me such an error
int(*array)[160] = malloc((sizeof *array) * 10);
and doing something like this
int** Make2DintArray(int arraySizeX, int arraySizeY) {
int** theArray;
theArray = (int**) malloc(arraySizeX*sizeof(int*));
int i;
for (i = 0; i < arraySizeX; i++)
{
theArray[i] = (int*) malloc(arraySizeY*sizeof(int));
}
return theArray;
}
will get me this
"void *(size_t)" in "memory.c" at line 239 and: "int()"
does anyone have a solution for how to successful allocate a 2dArray of int[160][10]
Try this:
int **array;
array = malloc(rows * sizeof(int *));
for (i = 0; i < rows; i++)
array[i] = malloc(cols * sizeof(int));
// Some testing
for (i = 0; i < rows; i++) {
for (j = 0; j < cols; j++)
array[i][j] = 0; // or whatever you want
}
for (i = 0; i < rows; i++) {
for (j = 0; j < cols; j++)
printf("%d ", array[i][j]);
}
In your case rows = 160 and cols = 10. Is one possible solution.
With this approach you can use the two indexes:
Both of these compile fine for me. The first error is common when you forget to #include <stdlib.h> prior to using functions declared within said-same (such as malloc(size_t)), which I did not forget to do.
C has some interesting compile-time behaviors, among them the ability to invoke a function that has never been seen before (neither prototype definition nor implementation). Upon encountering such a call, C assumes the function is:
Something that returns int
Takes an unknown number of arguments, so the caller can pass whatever it wants (including the wrong things).
Eg., the function is implicitly assumed to be of the form:
int func();
Often you won't even notice, save for warnings from your compiler that report something to the effect of:
Warning: implicit declaration of `func` assumed to return `int`
and if you're on-the-ball, you have your warning levels turned up with warnings-as-errors enabled and will catch this.
But what if you don't? And what if the "thing" returned from the function cannot be content-represented by the data size in an implementation int ? What if, for example, int were 32-bit, but data pointers were 64-bit? For example, lets assume char *get_str() is declared in some header file you're not including, and implemented in a .c file you compile and link with your program, that looks like this:
#include <stdio.h>
// Note: NO prototype for get_str
int main()
{
char *s = get_str();
printf("String: %s\n", s);
return 0;
}
Well, the compiler should puke, telling you that int and char* are not compatible (shortly after it warns you get_str is assumed to return int). But what if you force the compiler's hand by telling it to make a char* one way or another:
#include <stdio.h>
// Note: NO prototype for get_str
int main()
{
char *s = (char*)get_str(); // NOTE: added cast
printf("String: %s\n", s);
return 0;
}
Now, without warnings-as-errors enabled, you'll get a implicit declaration warning, and thats it. The code will compile. But will it run ? If sizeof(int) != sizeof(char*), (32-bit vs 64-bit) likely not. The value returned from get_str is a 64-bit pointer, but the caller is assuming only 32-bits is returned, then forcing it to a 64-bit pointer. In short, the cast has hidden the error and opened pandora's box of undefined behavior.
So how does all of this relate to your code? By not including <stdlib.h> the compiler doesn't know what malloc is. So it assumes it is of the form:
int malloc();
Then, by casting the result to (int**) you're telling the compiler "whatever comes out of this, make it a int**". At link time, _malloc is found (no parameter signature via name mangling like C++), wired up, and your program is ready to party. But on your platform int and data pointers are not the same size, thus you end up with several undesirable consequences:
The cast hides the real error.
A bogus pointer is manufactured from half the bits of the real returned pointer.
As a cruel dose of salt to the wound, the allocated memory is leaked, as there are no valid pointers anywhere that reference it (you just destroyed the only one by only keeping half of it).
Probably the most undesirable, the code will exhibit normal behavior if compiled on an implementation where sizeof(int) == sizeof(int**).
So you build this on your 32-bit Debian box, all looks well. You turn in your homework to the professor who builds it on his 64bit Mac and it crashes, you fail the assignment, fail the class, drop out of college, and spend the next ten years petting the cat while watching Seinfeld reruns in your mom's basement wonder what went wrong. Ouch.
Don't treat casting like some silver bullet. It isn't. In C, it is needed far less often than people use it, and if used in the wrong place, can hide catastrophic errors. If you find a point in your code where something won't compile without a hard cast, look again. Unless you're absolutely, positively sure the cast is the right thing to do, odds are its wrong.
In this case it hid the real error, that you neglected to give enough info to your compiler to know what malloc really does.
To allocate the array:
int *array = malloc(sizeof(int) * 160 * 10);
Then use code like:
array[10 * row + column] = value;
(Where row goes from 0 to 159 inclusive and column goes from 0 to 9 inclusive.)
I have a note for rendon's answer:
For his code, Visual C++ says for every "=" operations: error C2440: '=' : cannot convert from 'void *' to 'int **'
By making some changes, it works for me, but I'm not sure that it does the same, so I afraid of editing his code. Instead, here's me code, that seems to work for a first impression.
int **a;
a = (int **)malloc(rows * sizeof(int));
for (i = 0; i < rows; i++)
{
a[i] = (int *)malloc(cols * sizeof(int));
}
for (j=0;j<rows;j++)
{
for (i=0;i<cols;i++)
{
a[i][j] = 2;
}
}
Actually, I did it with a custom struct instead of ints but I think either way should it work.
Don't mind me I'm just adding an example using calloc
void allocate_fudging_array(int R, int C)
{
int **fudging_array = (int **) calloc(R, sizeof(int *));
for(int k = 0; k < R; k++)
{
fudging_array[k] = (int*) calloc(C, sizeof(int));
}
}
// a helper function to print the array
void print2darr(int **arr, int R, int C)
{
for(int i = 0; i < R; i++)
{
for(int j = 0; j < C; j++)
{
printf(" %d ", arr[i][j]);
}
printf("\n");
}
}
2D array to store char *
char ***array;
int rows = 2, cols = 2, i, j;
array = malloc(sizeof(char **)*rows);
for (i = 0; i < rows; i++)
array[i] = malloc(cols * sizeof(char *));
array[0][0] = "asd";
array[0][1] = "qwe";
array[1][0] = "stack";
array[1][1] = "overflow";
for(i=0;i<rows;i++){
for(j=0;j<cols;j++){
printf("%s ",array[i][j]);
}
printf("\n");
}
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.