C Strings in Structs - c

I want my struct to carry a string. I defined it like so:
typedef struct myStruct {
char* stringy
} myStruct
and a function
free(char *stringy){
//structObj is a struct object
structObj->stringy = stringy
}
Is this correct? I have a feeling that since it's a local variable, stringy will be lost, and the pointer will point to garbage.
Sorry, new with C.

It would be garbage if you were somehow using char** stringy, but structObj->stringy = stringy means "you know the thing that stringy points to? Now structObj->stringy points to that". Of course, it is still possible to unset the value which the pointer is pointing to, and at that point dereferencing will yield garbage.
Here's an example to make it clearer:
#include<stdio.h>
typedef struct mStruct {
char* stringy;
} myStruct;
myStruct * structObj;
void doSomething(char* stringy)
{
structObj->stringy = stringy;
}
int main(int argc, char* argv)
{
char* a = "abc\n";
structObj = malloc(sizeof(myStruct));
doSomething(a);
a = "qxr\n";
printf(structObj->stringy);
}// prints "abc\n"

If stringy is defined in callers of free function, as long as they keep the actual string in its place (where stringy points), no problem.

There is not any local variable declaration in your code.
You have to declare:
typedef struct myStruct {
char* stringy
} myStruct;
free(char *stringy){
myStruct *structObj;
structObj->stringy = stringy;
}
Pay attention to the semicolon that I've added to the end of the typedef declaration.
This was not not in your code.
The object structObj is a struct whose type is myStruct.
Now, your parameter stringy comes from another site, it is not lost.
But the struct structObj will have duration only inside your "free" function.
EDIT
I have fixed an error: the right declaration has to be "pointer to structObj", which is done in this way:
myStruct *structObj;
Observe that now myStruct is a non-initialized pointer, so the following assignment is legal:
structObj->stringy = stringy;
but will not work.
However I think this goes beyond the scope of the original question...

myStruct is type which you defined for your struct myStruct .that to you need to create an object before using.
you need to do like this:
typedef struct myStruct {
char *stringy;
} myStruct_t; //user defined data type
myStruct_t *obj;
// you need to allocate memory dynamically.
obj= (myStruct_t *) malloc(sizeof(myStruct_t));
usage:
scanf("%s",obj->stringy);
printf("%s",obj->stringy);
in function:
my_free(char *str) //str is local string
{
obj->stringy=str;
}
your can also try this code :
typedef struct myStruct {
char stringy[20]; //char *stringy
} myStruct_t; //user defined data type
myStruct_t obj; //object creation
usage:
scanf("%s",obj.stringy);
printf("%s",obj.stringy);
in function:
my_free(char *str) //str is local string
{
strcpy(obj.stringy,str);
}

You're correct that as soon as what it points to goes out of scope, it will point to garbage: this is a dangling pointer. You'll need to allocate some memory and perform a copy to fix this:
add_string(my_struct* s, const char* c)
{
size_t len = strlen(c);
s->file = malloc(len + 1);
strcpy(s->file, c);
}
Don't forget that you'll need to free it when you're done:
void destroy_struct(my_struct* s)
{
free(s->file);
free(s);
}

Related

Modifying a const pointer in C

I am trying to understand why the following code compiles and runs fine. I would expect any assignment using data inside f not to compile with a gcc error assignment of member ā€˜iā€™ in read-only object. Is there some kind of exception, because data.i is allocated dynamically?
#include <stdio.h>
#include <stdlib.h>
struct a {
int *i;
};
void f(const struct a *data) {
data->i[0] = 55;
}
int main() {
struct a data;
data.i = malloc(2 * sizeof(int));
f(&data);
printf("%d\n", data.i[0]);
return 0;
}
const front of a struct will make it read-only. If the struct contains pointer members, then those pointers themselves will turn read-only. Not what they point at.
That is, const struct a will make the member i behave is if it was declared as int *const i;, meaning that the pointer itself cannot be changed to point elsewhere. The pointed-at data is still of read/write int though.
If you want to restrict access to i inside a function, you should make that function take a const int* parameter and pass the i member to that function.
In the below code, const indicates what data points to is not to be modified. data->i[0] = 55; does not modify the pointer data->i. Instead that line of code modifies the memory pointed to by data->i. This is allowed as pointer .i is int * and not const int *.
struct a {
int *i;
};
void f(const struct a *data) {
data->i[0] = 55;
}
You cant modify i but you can modify the objects referenced by i.
To prevent it you need to:
struct a {
const int *i;
};

how to control struct member behavior with struct const pointer as function parameter?

I have a C code, somewhat similar to this:
struct st
{
int *var;
}
void fun(st *const ptr)
{
// considering memory for struct is already initialized properly.
ptr->var = NULL; // NO_ERROR
ptr = NULL; // ERROR, since its a const pointer.
}
void main()
{
//considering memory for struct is initialized properly
fun(ptr);
}
I dont want to declare int *var as const in the structure definition, so as not to mess with the huge code base. Not looking to make any change in the structure definition
Is there any way in C, to get an error for the NO_ERROR line
ptr->var = NULL; // NO_ERROR ?
Just declare the parameter with const, so the ptr is a pointer to a const object:
void fun(const struct st* ptr)
Your declaration makes ptr to be constant, but not the object to which it points. Also don't miss struct keyword
void fun(struct st *const ptr);
Instead you should use
void fun(const struct st *ptr);
Such declaration allows to change pointer but not the object to which it points.
Keep this in mind:
With type* const ptr, you cannot change the pointer but you can change the pointed data
With const type* ptr, you can change the pointer but you cannot change the pointed data
So all you need is to replace struct st* const ptr with const struct st* ptr.
Superb! Thank you so much guys!
I did this -
void fun(const struct st *const ptr);
and I was able to get an error while changing both ptr and ptr->var .. Just what I needed..

Unable to assign values in a structure

I have declared the structure:
typedef struct keyValuePairs{
char* type;
char* key;
char* valueType;
char* value;
} keyValueType;
keyValueType keyValuePairs[1000];
And in a function declared the local variables as:
char key[500];
char value[500];
to hold the key value pair values as:
key[i]="abc";
value[i]="xyz"
I have assigned these local variables to the global variable as:
keyValuepairs[1].key=key.
Once i come out of the function, the values assigned in the structure is getting lost. Can someone explain where I am going wrong?
Please note I am fairly new to C.
Both key and value variables are pointers to arrays that are allocated in the stack when you are in the function. After keyValuepairs[1].key=key the global variable points to that same place in the stack. After exiting the function, the memory where those arrays were is reused.
I suggest you read up on static vs dynamic allocation in C
If I understand you correctly, you are trying something along the lines of:
typedef struct
{
char* val;
} A;
A alist[10];
void foo()
{
char t[10];
t = "abc";
alist[0].val = t;
}
int main()
{
foo();
}
First of all, the line
t = "abc";
is syntactically incorrect. You have to use something like:
strcpy(t, "abc");
But the most important error is that when you return from foo, alist[0].val points to an address that is not good any more. To make sure alist[0].val points to a valid address, you have to allocate memory from the heap for it and copy the contents of t to it.
void foo()
{
char t[10];
strcpy(t,"abc");
alist[0].val = malloc(strlen(t)+1);
strcpy(alist[0].val, t);
}
To do a thorough job, you'll have to make sure that you call free on that allocated memory at some point before you return from main.
You have not allocated memory for type, key, valueType and value.
Try static memory allocation :
typedef struct keyValuePairs{
char* type[n];
char* key[n];
char* valueType[n];
char* value[n];
}
Where n is a defined constant

C void Pointer on mainframe

I'm currently working on modifying a dump program, but I can't figure out how to properly navigate with a void pointer. Below is the function that I'm working in, and the instruction that I'm trying to execute. I've tried casting mem to a struct, but I'm not sure of the sytnax and I keep getting an error. For the code below, the specific error I'm getting is:
47 | mem = mem->tcbtio
===========> .........a..............................................
*=ERROR===========> a - CCN3122 Expecting pointer to struct or union.
Here is my function:
void hexdump(void *mem, unsigned int len)
{
mem = mem->tcbtio;
...
}
Here are my struct defintions:
struct psa {
char psastuff[540];
struct tcb *psatold;
char filler[4];
struct ascb *psaaold;
};
struct tcb {
struct prb *tcbrb;
char tcbstuff[8];
struct tiot *tcbtio;
};
struct tiot {
char tiocnjob[8];
char tiocpstn[8];
char tiocjstn[8];
};
I need to keep it as a void pointer, as I need to cast it to char and int later on in the function.
It seems as you are expecting to find a tcb struct, starting at the address pointed by mem, but the aim of the code is obscure and the question not clear.
If this is really the case, you can try this:
mem = ((struct tcb *)mem)->tcbtio;
You cannot dereference a void pointer. You can think it this way if you have a void pointer, how will compiler know what type of address it is holding. And by doing mem = mem->tcbtio how much offset it has to make.
Modify your function as:
void hexdump(void *mem, unsigned int len)
{
struct tcbtio *mem2;
mem2 = ((struct tcb*) mem) -> tcbtio;
...
// Use mem2 later
}

Passing a struct into a generic function in C

I declare a new struct with the name of "Struct"
I have a generic function that takes in an argument "void *data".
void Foo(void *data)
I pass an instance of "Struct" into the generic function.
Struct s;
Foo(&s);
I want to access one of the properties of the struct in the function.
void Foo(void *data) {
char *word = (char*) data.word;
}
It's not allowed because it doesn't recognize data as a valid struct.
I even try to declare the data as the struct type first, and I get an error.
void Foo(void *data) {
Struct s = (Struct) data;
char *word = s.word;
}
I get "conversion to non-scalar type requested".
First of all, you should turn on your compiler's warning flags (all of them). Then you should pass a pointer to your Struct and use something other than struct as a variable name:
Struct s;
Foo(&s);
Then, in Foo:
void Foo(void *data) {
Struct *s = data;
char *word = s->word;
}
You can't convert non-pointer types to and from void* like you're trying to, converting pointer types to and from void* is, on the other hand, valid.
You need to pass a pointer to you struct and get a pointer to the struct inside the function:
Struct struct;
Foo(&struct);
void Foo(void *data) {
Struct* struct = (Struct*) data;
char *word = struct->word;
}
You have to use -> operator when requesting structure member via pointer.
This should work: char *word = (char*) data->word;
You also have to pass the address of the structure to the function. Like this: Foo(&struct);.
Firstly you need to call the function correctly:
Struct s;
Foo(&s);
Notice you're now passing a pointer to the structure.
Now, the function has to know that you're using a Struct (as opposed to something else) - perhaps because of another parameter, or a global variable, or some other reason. Then inside the function you can do:
void Foo(void *data) {
Struct *structpointer = p; /* Note - no need for a cast here */
/* (determine whether data does refer to a pointer then...) */
char *word = structpointer->word;
/* ... then use 'word'... */
}
Data is pointer, so whatever you cast it to must also be a pointer. If you said Struct* myStruct = (Struct*) data, all would be well with the world.
You are mixing pointers and data.
Struct struct defines a data object
void *data expects data to be a pointer.
Call Foo with a pointer to a Struct, and make other necessary changes
Struct struct;
Foo((void*)&struct);
void Foo(void *data) {
Struct *struct = (Struct*)data;
char *word = struct->word;
}
or the more compact form:
Struct struct;
Foo((void*)&struct);
void Foo(void *data) {
char *word = ((Struct*)data)->word;
}

Resources