I have a certain struct structXand a 2D array which holds these kind of structs.
I want to be able to save a pointer to that 2D struct and iterate over it
in a dynamic way, meaning, the pointer can hold any structX and iterate.
Example in general lines:
struct structX *ptr = NULL;
...
if(i == OK)
{
ptr = General_struct_which_holds_others->ptr1;
}
else if(i ==NOT_OK)
{
ptr = General_struct_which_holds_others->ptr2;
}
Now the iteration:
if(ptr[x][y] == OK) <----Error, subscripted value is neither array nor pointer
{
...
}
I hope i'm understood, As i was saying this is very general.
How can the iteration be made? meaning not getting errors?
Thanks!
Two problem I can noticce in your code if(ptr[x][y] == OK)
(1):
ptr is pointer to structure (single *) you can't use double indices [][] so error at if(ptr[x][y] == OK)
error, subscripted value is neither array nor pointer because of ptr[][]
(2):
error: used struct type value where scalar is required means if(struct are not allow).
if(should be a scalar value )
scalar value means can be convert into 0/1.
Pointer to 2D struct array C
struct structX matrix2D[ROW][COL];
its pointer
struct structX (*ptr2D)[ROW][COL];
ptr2D = &matrix2D;
ok, access you array structure like this:
struct structX i;
(*ptr2D)[r][c] = i;
If you want to pass in an function do like:
void to(struct structX* ptr2D[][COL]){
struct structX i;
ptr2D[][COL] = i;
}
void from(){
struct structX matrix2D[ROW][COL];
to(matrix2D);
}
Just to make you sure I written a simple code shows how to work with ptr2D. Hope you find it helpful:
#include<stdio.h>
#define ROW 10
#define COL 5
typedef struct {
int a;
char b;
} structX;
void to(structX ptr2D[][COL], int r, int c){
printf("in to: %d %c\n", ptr2D[r][c].a, ptr2D[r][c].b);
}
int main(){
structX matrix[ROW][COL];
structX (*ptr2D)[ROW][COL];
ptr2D = &matrix;
structX i;
i.a = 5;
i.b = 'a';
int r = 3;
int c = 2;
(*ptr2D)[r][c] = i;
printf("%d %c\n", (*ptr2D)[r][c].a, (*ptr2D)[r][c].b);
to(matrix, r, c);
}
And its working, Output:
5 a
in to: 5 a
EDIT
I wanted to show two tricks but now I think I should provide a uniform method(as you commented):
So here is the code:
#include<stdio.h>
#define ROW 10
#define COL 5
typedef struct {
int a;
char b;
} structX;
void to(structX (*ptr2D)[ROW][COL], int r, int c){
printf("in to: %d %c\n", (*ptr2D)[r][c].a, (*ptr2D)[r][c].b);
}
int main(){
structX matrix[ROW][COL];
structX (*ptr2D)[ROW][COL];
ptr2D = &matrix;
structX i;
i.a = 5;
i.b = 'a';
int r = 3;
int c = 2;
(*ptr2D)[r][c] = i;
printf("%d %c\n", (*ptr2D)[r][c].a, (*ptr2D)[r][c].b);
to(&matrix, r, c);
}
Output
5 a
in to: 5 a
EDIT:
error: used struct type value where scalar is required means if(struct are not allow).
if(should be a scalar value )
you can't do like if((*ptr2D)[r][c]);
but this is allow:
if((*ptr2D)[r][c].a == 5);
or
if((*ptr2D)[r][c].b == 'a');
or
if((*ptr2D)[r][c].a == 5 && (*ptr2D)[r][c].b == 'a');
or
structX i;
if((*ptr2D)[r][c] == i);
You might want to ready this article about multidimensional arrays. If you want to iterate over an array, you need to know how big it is (whether it is dynamic or not). If you want it to be dynamic, that means you need to allocate memory for it when it needs to grow and you need to free the old memory. You also have a problem in your question - you declare a single pointer which is null and then try to dereference it but you never allocated memory for it.
If you did allocate memory for it, you could dereference it by saying
ptr[x * ROW_WIDTH + y]
if you set ROW_WIDTH to the maximum value of y. Depending on whether you want to represent a rows major or column major array, you might use y * width instead of x * width.
Related
I got this code:
#include <stdio.h>
#include <string.h>
int main(void)
{
int a[3]={1,2,3},
b[3];
int (*p)[3]= &a;
b = p;
for(int i=0;i<3;i++)
printf("%i",b[i]);
}
-I wanted output to be like "123", but I am having problems assigning the b array to what the p is pointing.
ps -
memcpy( b, p, sizeof(b)); does just what i want but i want to do it without the use of that function.
The line
b = p;
has a couple of problems. First of all, array expressions may not be the target of the = operator; you can't assign an entire array in a single operation like that1.
Secondly, the types don't match; p has type int (*)[3], while b has type int [3]. Arrays are not pointers - array expressions "decay" to pointer expressions under most circumstances, but in this case even the pointers would be of incompatible types (b would decay to an expression of type int *, not int (*)[3]).
No, the only ways to copy the contents of one array to the other are to use library functions like memcpy or to use a loop to assign each element individually:
for ( size_t i = 0; i < 3; i++ )
b[i] = (*p)[i]; // or b[i] = a[i]
That's it.
Initialization is different from assignment.
Arrays do not have the assignment operator. You need somehow to copy elements of one array to another array.
Without using the standard function memcpy you can use an ordinary loop as for example
for ( size_t i = 0; i < sizeof( a ) / sizeof( *a ); i++ )
{
b[i] = a[i];
}
Or if to use intermediate pointers you can write
for ( int *p = a, *q = b; p != a + sizeof( a ) / sizeof( *a ); ++p )
{
*q++ = *p;
}
You have a small fixed size array, perfectly suitable for wrapping inside a struct, so you can do this:
#include <stdio.h>
#include <string.h>
struct ia3 {
int data[3];
}
int main(void)
{
struct ia3 a = {{1,2,3}};
struct ia3 b;
struct ia3 *p = &a;
b = *p; // struct assignment
for(int i=0;i<3;i++) {
printf("%i",b.data[i]);
}
}
"...but i want to do it without the use of [memcpy(,,)]."
It is unclear why using memcpy() is not agreeable in this exercise, but it does do the task more efficiently then loop for large array sizes.
If you just want a pointer to the array...
int a[3] = {1,2,3};
//create pointer
int *b = a;//does not copy array a, just points to it
//If an additional array is needed, do this...
int b[3] = {0};
int i = 0;
//to copy, without memcpy(), use this alternative.
for(i=0; i<3; i++) b[i] = a[i];//makes copy of array a
for(i=0;i<3;i++)
printf("%i", b[i]);
I need to have dynamic memory allocation without the use of malloc in an embedded application.
As we have enough RAM, I would like to allocate a big array (A[A_MAX]) on startup and have buffer arrays (B[]) within this one big array.
They would always begin at A[0] and be as long as they need (at max A_MAX, but mostly shorter).
Example:
at start up:
A[8] = {0,0,0,0,0,0,0,0};
declaring B[4] at A[0] and filling B with ones
B[4] = {1,1,1,1};
now A should look like this:
A[8] = {1,1,1,1,0,0,0,0}
How can I do this?
I looked at the sourcecode for malloc() and it does return the address of the next free part of the heap.
but when I use
float *B[4] = &A[0];
my compiler returns an error (invalid initializer)
As #neon mentioned I wanted to write an address to a float array.
Writing it like float *B = A[0] worked like a charm.
You may do:
#include <stdalign.h>
#define A_MAX 8
alignas(max_align_t) char _memory[A_MAX] = {0};
then you can just use pointers:
int main() {
{
float *floatdata = (void*)_memory;
// use floatdata
}
{
int *intdata = (void*)_memory;
// use intdata
}
}
I would write a handy function to calculate the maximum size for error checking:
// query the max size and allocate
inline void *dataalloc(size_t elemsize, size_t *n) {
*n = sizeof(_data) / elemsize;
return _data;
}
and do:
size_t size;
float *floatdata = dataalloc(sizeof(*floatdata), &size);
// use as-if floatdata[size]
for (size_t i = 0; i < size; ++i) floatdata[i] = i;
do you mean something like ? I'm using pointers to the array
#include <stdio.h>
#include <stdlib.h>
void allocator(float* src,int SrcSize,float **dst,int size,int pos){
if(size <= SrcSize)
for(int i=0;i<size;i++){
dst[i] = &(src+pos)[i];
}
}
int main()
{
float A[8] = {0,0,0,0,0,0,0,0};
float *B[4];
float *C[4];
allocator(A,sizeof(A)/sizeof(float),B,4,0);
*B[2] = 4;
allocator(A,sizeof(A)/sizeof(float),C,4,4);
*C[0] = 6;
printf("A[2] value is : %f\n" , A[2]); // output is 4.000
printf("A[4] value is : %f\n" , A[4]); // output is 6.000
return 0;
}
I have the following code:
#include<stdio.h>
struct student {
int* grades;
int num_grades;
};
double* get_means(struct student* arr, int n); // Function Signature
// grade range is: 0 - 100
// assume max number of grades to one student is up to 100
double* get_means(struct student* arr, int n)
{
arr->grades = 90;
printf("%d", arr->grades);
}
int main()
{
struct student s, *p;
s.grades = malloc(s.num_grades * (sizeof(int)));
p->grades[0] = 1;
printf("%d", p->grades[0]);
}
and I'm having an issue assigning a value (it doesn't matter what the value is, it can be: 0, 7, 50).
The compiler gives me the error:
Error C4700 uninitialized local variable 's' used
Error C4700 uninitialized local variable 'p' used
What can I do to fix this?
In other words: how do I assign a value to an array in a struct?
When you try to do that p->grades[0] = 1 first you need to assign the address for s to p and only than trying to access s from the pointer p. Second issue here is you trying to access array only through is name (in the function get means), As you know array name its only the base address of the array its not the value in it. Third issue its the function does not return nothing but in the prototype it returns pointer to double, I suggest you to change it to avoid any unnecessary warnings or errors.
And another suggestion is including <stdlib.h> when using malloc and always check malloc does not returns you NULL.
The fixed code attached:
struct student {
int* grades;
int num_grades;
};
void get_means(struct student* arr, int n);
void get_means(struct student* arr, int n)
{
arr->grades[0] = 90;
printf("%d", arr->grades[0]);
}
int main()
{
struct student s, *p;
s.grades = malloc(s.num_grades * (sizeof(int)));
/* Option 1
s.grades[0] = 1;
printf("%d", s.grades[0]);
*/
/* Option 2 */
p = &s;
p->grades[0] = 1;
printf("%d", p->grades[0]);
}
I need to get a pointer to a 2D array. The sizes ARE known at compile time if that helps. I need to perform an action a certain array based on the incoming value of a variable.
//Global arrays
// int c[6000][1000];
// int a[6000][1000];
void fun(int x){
//Setup a pointer here
//Possible solution: int (*pointer)[6000][1000];
int **pointer;
if (x == 0){
pointer = c;
}
else{
pointer = a;
}
//Modify pointer here and have changes reflect back to the array it was based off of
pointer[0][17] = 42;
}
I have looked at close to a dozen different stack overflow articles on how to do this but I cannot find a way to just a get a simple pointer to a 2D array.
//Global arrays
int c[6000][1000];
int a[6000][1000];
void fun(int x) {
int (* ptr)[1000];
if (x == 0) {
ptr = c;
} else {
ptr = a;
}
ptr[0][17] = 42;
}
Like this
//Global arrays
int c[6000][1000];
int a[6000][1000];
void fun(int x) {
if (x == 0) {
c[0][17] = 42;
} else {
a[0][17] = 42;
}
}
Accessing a 2D array using Pointers:
2D array is an array of 1D arrays which implies each row of a 2D array is a 1D array. So, think about two of your global arrays,
int c[6000][1000] and int a[6000][1000].
We can say c[0] is the address of row 0 of the first global 2D array. Similarly a[6000] is the address of row 6000 of the second global 2D array.
Now you want to find the c[0][17] and point that using a pointer which is basically, c[0][17] = *(c[0] + 17).
Also you can write for any other array elements, c[0] = *c and in general each element as, c[i][j] = *(c[i] + j) = ((c+i) + j).
So, if c is a 2D array of integer type then we can think that c is a pointer to a pointer to an integer which can be interpreted as int **c. Dereferencing *c gives you the address of row 0 or c[0] which is a pointer to an integer and again dereferencing c[0] gives you the first element of the 2D array, c[0][0] which is an integer.
You can test your code by accessing each element using pointer for a better understanding:
#include<stdio.h>
#include<stdlib.h>
//Global arrays
int c[6000][1000];
int a[6000][1000];
void fun(int x){
//Setup a pointer here
//Possible solution: int (*pointer)[6000][1000];
int (*pointer)[1000];
if (x == 0){
pointer = c;
}
else{
pointer = a;
}
//Modify pointer here and have changes reflect back to the array it was based off of
pointer[0][17] = 42;
}
int main(){
int num;
scanf("%d", &num);
fun(num);
if(num == 0){
printf("When num is %d, c[0][17] = %d\n", num, *(*(c) + 17));
}
else{
printf("When num is %d, a[0][17] = %d\n", num, *(a[0] + 17));
}
return 0;
}
I'm coming from c#, and this is causing me more issues than I would've expected. I've not seen a straight forward solution to this. I'm brand new to C, just playing with it, and all of the various implementation I've tried, from using structs, to passing pointers around isn't getting the job done. (local values aren't changing). Can someone give me a cut and dry example?
Here's a sample of my code
#include <stdio.h>
//alter values based on input
int * doStuff(int a, int b){
int input;
int arr[2]
scanf("%d", &option);
switch(option);
case 1:
arr[0] = a-2;
arr[1] = b;
return arr;
break;
case 2:
arr[0] = a;
arr[1] = b-2;
return arr;
break;
default:
return a, b;
}
main(){
int a = 20;
int b = 20;
int returnedObject[2];
//what i need is like in c# how I can do this
returnedObject = doStuff(a, b);
a = returnedObject[0];
b= returnedObject[1];
}
I need to pass values, alter them, return them, and set the local variables. I'm completely lost with some of the more complex examples. Coming from c# pointers, arrays, how they work is losing me, and it isn't as simple as I had expected.
Functions in C cannot return array types, nor can arrays be the target of an assignment. So code like
int returnedObject[2];
returnedObject = doStuff( a, b );
cannot work. C functions can return pointers to arrays, but I don't think you want to get into that.
C functions cannot return multiple objects, nor is multiple assignment supported.
If your two values are logically attributes of some larger, aggregate type, you can use a struct type to return a single object with multiple attributes, such as
struct result { int x, int y };
struct result doStuff( int a, int b )
{
struct result ret = {a, b}; // initialize struct with inputs
...
case 1:
ret.x = a-2;
break; // y remains unchanged
case 2:
ret.y = b-2;
break; // x remains unchanged
...
return ret;
}
which you would call as
struct result stuff;
stuff = doStuff( a, b );
Alternately, you can pass pointers to your values and update them as necessary:
void doStuff( int *a, int *b )
{
...
case 1:
*a = *a - 2;
break;
case 2:
*b = *b - 2;
break;
}
which you would call as
doStuff( &a, &b );
In this case you don't actually return anything to the caller.
You can pass an array as an argument to the function, like so:
void doStuff( int a, int b, int *result )
{
result[0] = a;
result[1] = b;
...
case 1:
result[0] = a - 2;
break;
case 2:
result[1] = b - 2;
break;
...
}
which you would call as
int results[2];
int a;
int b;
...
doStuff( a, b, results );
Note that when we pass the array expression to the function, its type is changed from int [2] to int *. Except when it is the operand of the sizeof or unary & operators, or is a string literal used to initialize another array, an expression of type "N-element array of T" will be converted ("decay") to an expression of type "pointer to T", and the value of the expression will be the address of the first element of the array. Array expressions in C lose their "array-ness" in most circumstances1. You can use the subscript operator [] on a pointer expression as you would an array expression (the array index operation a[i] is defined as *(a + i)), but pointers are not arrays and vice versa.
1. Note that I'm talking about the expression, not the object. The array object always stays an array object.
Simple solution (Passing by reference/pointer allows to change the value stored)
#include <stdio.h>
//alter values based on input
void doStuff(int *a, int *b, int option)
{
switch(option)
{
case 1:
// a decremented by 2, b is unchanged
*a = *a - 2;
break;
case 2:
// b decremented by 2, a is unchanged
*b = *b - 2;
break;
default:
// a and b are unchanged
break;
}
}
int main()
{
int a = 20;
int b = 20;
int option;
printf("Enter option (1 or 2):\n");
scanf("%d", &option);
printf("BEFORE doStuff() :: a = %d, b = %d\n", a, b);
doStuff(&a, &b, option);
printf("AFTER doStuff() :: a = %d, b = %d\n", a, b);
return 0;
}
You can wrap the array with a struct to return it directly.
#include <stdio.h>
struct doStuffRet {
int arr[2];
};
//alter values based on input
struct doStuffRet doStuff(int a, int b){
int option;
struct doStuffRet r = {{a, b}};
scanf("%d", &option);
switch(option) {
case 1:
r.arr[0] = a-2;
r.arr[1] = b;
return r;
break;
case 2:
r.arr[0] = a;
r.arr[1] = b-2;
return r;
break;
default:
return r;
}
}
int main(void){
int a = 20;
int b = 20;
struct doStuffRet returnedObject;
//what i need is like in c# how I can do this
returnedObject = doStuff(a, b);
a = returnedObject.arr[0];
b = returnedObject.arr[1];
printf("%d %d\n", a, b);
return 0;
}
Make the return type int *.
Create a local variable int *result = malloc(sizeof(int) * 2); and put your a and b or whatever you need to return in result.
When you call the function, assign the result to an int *.
int *res;
res = doStuff(a, b);
a = res[0];
b = res[1];
malloc allocates space for result on the heap. Its input is the number of bytes you need.
2 ints, 4 bytes per int -> 8 bytes == 2*sizeof(int)
The problem is that every time you call your function, you will keep allocating more and more space. C doesn't do garbage collection for you, so when you're done using your int *res, you should free that space by calling free(res).
Further Details:
In C#, you would initialize an array like this: int[] result = new result[2];
Have you every tried printing an array like this Console.WriteLine(myarray);. It doesn't work does it? C# I believe prints something like System.Int32[]. If you did this in Java (System.out.println(myarray);), it would print some weird number.
That number is actually the address of the array.
When you reference your array myarray, you are actually referencing the address of the array. When you do something like myarray[1], you are getting the address of myarray, adding to it 1*sizeof(int) and fetching that value.
In C, you can define arrays in the typical way: int arr[2]; which allocates space for 2 ints.
Alternatively, you can do: int *arr; which defines a pointer (or address). However, you need to tell it to allocate space for integers. As it is now, arr doesn't really point to anything. You allocate space by calling malloc: arr = malloc(2*sizeof(int)); which dynamically allocates space for 2 integers.
Now you can put stuff in your array. arr[0] = 1.
The [] is effectively doing pointer arithmetic.
arr[1] is the same as *(arr + 1)
arr + 1 is getting the address of the array and adding 1 to it. C sees that you're adding to an int * so it interprets 1 to mean 1 int (4 bytes). The * operator dereferences the address, which means it follows the pointer and gets the value stored at that address.
If printing arr gives you 0x1000, arr+1 gives you 0x1004 and * will return the int stored at 0x1004.
On to returning arrays in functions.
In C, you can't return an array like in C# (int[] function(...)), but you can return a pointer (int *function(...)), which you can use like an array (see above example).
The reason you want to use malloc is because malloc allocates space on the heap, so you can use that array after the function returns. If you defined an array like int arr[2];, the space would be allocated on the stack, and the array wouldn't persist after the function returns.
Perhaps you should look at a tutorial to learn more about pointers. I think my answer is too lengthy and not totally relevant to the question.