C: 2d char pointer in a struct - c

I want to write and print some strings in a 2d array in a struct. The struct is called Router and it is in a header file, the 2d array is defined in that struct and it's called **addTab. When I try to print one line of the array using the function viewTable the program stopped working... why?
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "router.h"
#define N 8
#define M 3
#define sizeMess 5
Router *createRouter(){
Router *NewRouter=(Router*)malloc(sizeof(Router));
int i;
NewRouter->addTab=(char **) malloc(N*sizeof(char *));
for(i=0;i<N;i++)
NewRouter->addTab[i]=(char *) malloc(M*sizeof(char));
return NewRouter;
}
void viewTable(Router *r, int a){
int i,j;
for(i=0;i<N;i++){
for(j=0;j<M;j++){
printf("raw\t col\t address\t value\t\n");
printf("%d\t %d\t",i,j);
printf("%p\t",&r->addTab[i][j]);
printf("%s\t\n",r->addTab[i][j]);
}
}
}
void updateTable(Router *r, int conn, char *addr1, char *addr2){
r->addTab[conn][1]=addr1;
r->addTab[conn][2]=addr2;
}

First off: Don't cast the result of malloc.
Assuming that you want to store char* pointers in your 2D array (as the title of your question says), you will need to define it as char *** in your Router structure, like this:
typedef struct router {
char ***addTab;
} Router;
Next, you will need to change your createRouter function, so that it can store an array of char* pointers, instead of a single byte for each element, like so:
Router *createRouter(){
Router *NewRouter=malloc(sizeof(Router));
int i;
NewRouter->addTab=malloc(N*sizeof(char **));
for (i=0;i<N;i++)
NewRouter->addTab[i]=malloc(M*sizeof(char *));
return NewRouter;
}
I'm not sure how you call your updateTable function, but unless you actually fill up the entire array with char* pointers, your viewTable function will also invoke Undefined Behavior, because the printf statements will attempt to access uninitialized data. You could avoid this by using calloc instead of malloc when allocating the 2D array (or explicitly memset it), and then adding NULL checks in your viewTable function.
Finally, if you're calling updateTable with char* pointers that are not string literals or they have not been allocated on the heap, you might have further issues...

Your updateTable() doesn't work as you'd expect. You allocated memory in r->addTab[i][j] and, afterwards, assign a pointer to it (r->addTab[conn][1]=addr1). On access in viewTable, the program tries to read the memory at addr1, but most likely won't be able to read it, thus crashes.
Use a function to copy a given string to r->addTab, e.g. like so:
void router_tab_printf(Router *r, const int conn, const int i, const char *value) {
sprintf(r->addTab[conn][i], "%s", value);
}
This assumes that r->addTab[conn][i] is large enough to hold value.

you need to change your updateTable
void updateTable(Router *r, int conn, char *addr1, char *addr2){
strcpy(r->addTab[conn], addr1);
strcpy(r->addTab[conn+1 /*or something*/], addr2);
}

Related

Passing struct to function call doesn't work

Since C does not support pass by reference, and I'm developing something that cannot use heap memory, how can I make this work? I want the function call set_var_name to actually change the variables global_log instead of just a local copy. Thanks
#include <stdio.h>
struct Record
{
char type[1];
char var_name[1014];
void* var_address;
char is_out_dated[1];
};
struct Global_Log
{
struct Record records[1024];
int next_slot;
};
void set_var_name(struct Global_Log global_log, int next_slot, char* data, int size)
{
for(int i = 0 ; i < size; i++)
global_log.records[0].var_name[i] = data[i];
printf("%s\n",global_log.records[0].var_name);//here prints out "hello"
}
int main()
{
struct Global_Log global_log;
char a[6] = "hello";
set_var_name(global_log, 0, a, 6);
printf("%s\n",global_log.records[0].var_name); // here prints out nothing
return 0;
}
It seems that you are working with a copy of the struct instance, instead of a reference. Try passing a pointer of a struct as a parameter, so you can work with a reference of the instance:
void set_var_name(struct Global_Log* global_log, int next_slot, char* data, int size)
Another alternative is using a global variable, since it sounds like there won't be another instance of it.
C is a call-by-value language -- when you call a function, all arguments are passed by value (that is, a copy is made into the callee's scope) and not by reference. So any changes to the arguments in the function only affect the copy in the called function.
If you want to call "by reference", you need to do it explicitly by passing a pointer and dereferencing it in the called function.

Changing an array value from a function in C

The program crashes right in the instruction mentioned in the source code (I didn't write all the code because it's too long)
int main()
{
char screen[24][80];
//......every thing is well until this instruction
backgrounds(5,screen);
//......the program doesn't execute the rest of the code
}
//______________________________________________________
//this is a header file
void backgrounds(int choice,char **screen)
{
if(choice==5)
{
screen[18][18]='-';
screen[18][19]='-';
screen[18][20]='-';
}
}
A char [24][80] cannot be converted to a char **.
When passed to a function, an array decays into a pointer to its first element. This is simple for a 1 dimensional array, but less so for higher dimensions.
In this case, a char [24][80] is an array of char [80]. So passing a variable of this type to a function yields a char (*)[80].
Change your function definition to either this:
void backgrounds(int choice,char (*screen)[80])
Or this:
void backgrounds(int choice,char screen[24][80])
Or you can use a variable length array for maximum flexibility:
void backgrounds(int choice, int x, int y, char screen[x][y])

Change Array without returning it [C]

I just have a basic question concerning arrays in functions.
I am trying to change an array in a function without returning it.
I know how to do this for integers or doubles but i didn't know how to do this for arrays. So i experimented a little bit and now I am confused.
I have 2 variations of my code which i thought should do the same thing , but they don't. I pass the array b to the function Test. In the function I try to fill the array with the values 0, 1 ,2
#include <stdlib.h>
#include <stdio.h>
void Test(int * vector){
vector = malloc(3*sizeof(int));
int i;
for(i=0;i<3;i++){
*(vector+i)=i;
}
}
int main(){
int b[3];
Test(b);
printf("%i\n",b[0]);
printf("%i\n",b[1]);
printf("%i\n",b[2]);
return EXIT_SUCCESS;
}
This Version doesnt work, i don't get the expected result 0,1,2
This Code on the other hand does seem to work:
#include <stdlib.h>
#include <stdio.h>
void Test(int * vector){
int * b = malloc(3*sizeof(int));
int i;
for(i=0;i<3;i++){
*(b+i)=i;
*(vector+i) = *(b+i);
}
}
int main(){
int b[3];
Test(b);
printf("%i, ",b[0]);
printf("%i, ",b[1]);
printf("%i ",b[2]);
return EXIT_SUCCESS;
}
Can somebody explain to me why only the second one works?
Best Regards,
Rob
When you pass an array to a function, it decays into a pointer to the first element. That's what the function sees. But then you take the function parameter vector and overwrite it with dynamically allocated memory. Then you don't have access to the array you passed in. Additionally, you have a memory leak because you didn't free the allocated memory.
In the case of the second function you don't modify vector, so when you dereference the pointer you're changing b in main.
Also, instead of this:
*(vector+i)
Use this:
vector[i]
It's much clearer to the reader what it means.
test doesn't need to call malloc(). When you use an array as a function argument, it passes a pointer to the array. So you can simply write into vector[i] and it will modify the caller's array.
void Test(int * vector){
int i;
for(i=0;i<3;i++){
*(vector+i)=i;
}
}

Initializing arrays and structures in a function

I am trying to initialize an array of elements to a finite value in a c function.
one way i know is to use a for loop to initialize those values but I am wondering if there is a simple way? I know that they can be initialized during array declaration though but I wouldn't prefer that way.
ex:
int a[10];
void foo(void)
{
for (int i=0; i<10;i++)
{
a[i] = 10;
}
}
Thanks
For the special case, that it is an char/byte array you could use the memset function:
#include <string.h>
void * memset ( void * ptr, int value, size_t num );
Attention: Thoug an 'int' is passed to memset, the ptr will increase in char/byte steps. So it is not suitable for an int array!
But you could use memfill:
#include <publib.h>
void *memfill(void *buf, size_t size, const void *pat, size_t patsize);
See http://manpages.ubuntu.com/manpages/saucy/man3/memfill.3pub.html for details. But it is probably not everywhere available.

How to store result of type char in pointer?

I want to store result of type char in pointer which I'm passing as argument of function. Like this:
#include<stdio.h>
void try(char *);
int main()
{
char *result;
try(result);
printf("%s",result);
return 0;
}
void try(char *result)
{
result="try this";
}
But I'm getting result : (null)
Could someone tell me what's wrong here?
Your syntax only sends the pointer to the function. This allows changing the data the pointer points to, but not the pointer itself.
You would need to have
void try(char **result)
and call it
try(&result);
to change the actual pointer.
Another way is to copy data into the memory pointed by the pointer, but then you need to know there is enough memory available. Depends on the actual use case how to do it properly. You might use
strcpy(result, "what you want");
but then you really have to know that the memory pointed by result can handle 14 chars (remember the NULL in the end). In your current code you don't allocate memory at all for result, so this will invoke undefined behaviour.
The reason you're seeing NULL is because your compiler decided to initialize non-assigned pointers to NULL. Another compiler might initialize them to random values.
Also about terminology, you're not storing type char into a pointer. You may have a pointer pointing to a char, or in this case to a C type string, which is an array of chars.
You are creating another variable result inside try function.
Try printing result inside try function. It will work then.
If you really want to print inside main then try this -
#include<stdio.h>
void try(char **);
int main()
{
char *result;
try(&result);
printf("%s",result);
return 0;
}
void try(char** result)
{
*result = "try this";
//printf("%s\n",result);
}
Or if you don't want to get into double pointers, then this will work:
#include<stdio.h>
char* try(char *);
int main()
{
char *result;
result = try(result);
printf("%s",result);
return 0;
}
char* try(char* result)
{
result = "try this";
return result;
}
Also another way (no dynamic memory):
#include<stdio.h>
void try(char *);
int main()
{
char result[100] = {0};
try(result);
printf("%s",result);
return 0;
}
void try(char *result)
{
strcpy(result,"try this");
}
Note: When you say you got null, that doesn't mean anything - actually you had undefined behaviour there - because result was not initialized. I guess you invoked UB even before trying to print result, namely when you passed it to try. Because copy would be made in that method of the pointer, which would try to read value of original pointer - reading uninitialized variables is undefined in C. Hence always initialize your variables in C.

Resources