This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
I have a few questions about structs and pointers
For this struct:
typedef struct tNode_t {
char *w;
} tNode;
How come if I want to change/know the value of *w I need to use t.w = "asdfsd" instead
of t->w = "asdfasd"?
And I compiled this successfully without having t.w = (char *) malloc(28*sizeof(char));
in my testing code, is there a reason why tt's not needed?
Sample main:
int main()
{
tNode t;
char w[] = "abcd";
//t.word = (char *) malloc(28*sizeof(char));
t.word = w;
printf("%s", t.word);
}
Thanks.
t->w is shorthand for (*t).w i.e. it only makes sense to use the arrow if t is a pointer to a struct.
Also, since the string you assigned is hard-coded (thus, determined at compile time), there's no need to dynamically allocate its memory at runtime.
Take a look at this tutorial: http://pw1.netcom.com/~tjensen/ptr/ch5x.htm
struct tag {
char lname[20]; /* last name */
char fname[20]; /* first name */
int age; /* age */
float rate; /* e.g. 12.75 per hour */
};
kay, so we know that our pointer is going to point to a structure declared using struct tag. We declare such a pointer with the declaration:
struct tag *st_ptr;
and we point it to our example structure with:
st_ptr = &my_struct;
Now, we can access a given member by de-referencing the pointer. But, how do we de-reference the pointer to a structure? Well, consider the fact that we might want to use the pointer to set the age of the employee. We would write:
(*st_ptr).age = 63;
Look at this carefully. It says, replace that within the parenthesis with that which st_ptr points to, which is the structure my_struct. Thus, this breaks down to the same as my_struct.age.
However, this is a fairly often used expression and the designers of C have created an alternate syntax with the same meaning which is:
st_ptr->age = 63;
How come if I want to change/know the value of *w I need to use t.w =
"asdfsd" instead of t->w = "asdfasd"?
If your t is a pointer, you need to use t->w. Else you should use t.w.
in my testing code, is there a reason why tt's not needed?
In your code you have already set your t.word to point to the area storing your char w[] = "abcd";. So you don't need to malloc some memory for your t.word.
Another example where malloc is needed is:
tNode t;
t.word = (char *) malloc(28*sizeof(char));
strcpy(t.word, "Hello World");
printf("%s", t.word);
How come if I want to change/know the value of *w I need to use t.w =
"asdfsd" instead of t->w = "asdfasd"?
t is a tNode, not a pointer to tNode, so . is the appropriate accessor.
And I compiled this successfully without having t.w = (char *)
malloc(28*sizeof(char)); in my testing code, is there a reason why
tt's not needed?
This isn't needed because "abcd" is still in scope so w can just point to it. If you want w to point to persistent memory-managed contents, it will have to allocate its own memory as it would with this line.
Related
This question already has answers here:
Why, or when, do you need to dynamically allocate memory in C?
(3 answers)
Closed 5 years ago.
#include <stdio.h>
#include <stdlib.h>
typedef struct foo {
char* text;
int num;
} foo;
int main(void) {
foo* a = malloc(sizeof(foo));
a->text = "Something";
a->num = 4;
printf("%s %d\n", a->text, a->num);
foo b;
b.text = "Something";
b.num = 4;
foo* c = &b;
printf("%s %d", c->text, c->num);
return 0;
}
Both print the exact same thing. The only difference between foo* a and foo* c is where each one points to. Which one should be preferred? I usually see malloc() more but I don't understand why.
I think you should malloc() only for bigger data. You should consider that malloc() needs more time because it must find search for a data block in the heap and reserve it. If you use the struct on stack this is not necessary. So it really depends on what you are doing.
Edit: Also you should think of the scope of the variable. If the struct is needed only within the function I would prefer the stack.
Heap-allocated data is easier to share with others (i.e. across function boundaries), especially when the function that creates an object needs to have it usable when that function has exited. This is not possible with non-heap data (except when using static but that creates problems too), which can be rather limiting.
I am creating a symbol table for a compiler I am writing and when I try adding to my symbol table I keep getting valgrind errors. When I call my function, I am calling my add function
stAdd (&sSymbolTable, "test", RSRVWRD, 4, 9);
and in my stAdd function it is currently
void stAdd (StPtr psSymbolTable, char *identifier, SymbolTableType type,
int addressField, int arrayDimensions)
{
int hashValue;
hashValue = hash (identifier, psSymbolTable->numBuckets);
if (psSymbolTable->spSymbolTable[hashValue] == NULL)
{
psSymbolTable->spSymbolTable[hashValue] = (StEntryPtr) malloc (sizeof(StEntry));
strcpy (psSymbolTable->spSymbolTable[hashValue]->identifier, identifier);
psSymbolTable->spSymbolTable[hashValue]->entryLevel = psSymbolTable->currentLevel;
psSymbolTable->spSymbolTable[hashValue]->type = type;
psSymbolTable->spSymbolTable[hashValue]->addressField = addressField;
psSymbolTable->spSymbolTable[hashValue]->arrayDimensions = arrayDimensions;
psSymbolTable->spSymbolTable[hashValue]->psNext = NULL;
}
}
But every time I set a value within my StEntry struckt, I get an error
Use of unitialised value of size 8
every time I set something within the if statement. Does any see where I am going wrong?
My StEntry is
typedef struct StEntry
{
char identifier[32];
SymbolTableLevel entryLevel;
SymbolTableType type;
int addressField;
int arrayDimensions;
StEntryPtr psNext;
} StEntry;
This would be a lot easier if I could see the definition of struct StEntry or even the precise valgrind error. But I'll take a wild guess anyway, because I'm feeling overconfident.
Here, you malloc a new StEntry which you will proceed to fill in:
psSymbolTable->spSymbolTable[hashValue] = (StEntryPtr) malloc (sizeof(StEntry));
This is C, by the way. You don't need to cast the result of the malloc, and it is generally a good idea not to do so. Personally, I'd prefer:
StEntry* new_entry = malloc(sizeof *new_entry);
// Fill in the fields in new_entry
psSymbolTable->spSymbolTable[hashvale] = new_entry;
And actually, I'd ditch the hungarian prefixes, too, but that's an entirely other discussion, which is primarily opinion-based. But I digress.
The next thing you do is:
strcpy (psSymbolTable->spSymbolTable[hashValue]->identifier, identifier);
Now, psSymbolTable->spSymbolTable[hashValue]->identifier might well be a char *, which will point to the character string of the identifier corresponding to this symbol table entry. So it's a pointer. But what is its value? Answer: it doesn't have one. It's sitting in a block of malloc'd and uninitialized memory.
So when strcpy tries to use it as the address of a character string... well, watching out for the flying lizards. (If that's the problem, you could fix it in a flash by using strdup instead of strcpy.)
Now, I could well be wrong. Maybe the identifier member is not char*, but rather char[8]. Then there is no problem with what it points to, but there's also nothing stopping the strcpy from writing beyond its end. So either way, there's something ungainly about that line, which needs to be fixed.
This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
I am working on a project in which I need to read CSV lines from a text file into my program. I was given a code skeleton, and asked to fill in functionality. I have a struct containing a variable for each type of value I am going to receive, but my char array is causing segmentation faults.
Here is an excerpt of my code.
None of the exerpt is part of the given code, this is all mine:
My error is a Segmentation Fault(Core Dumped), due to the code within the get timestamp space.
my test file contained only one line,
5, 10:00:10, 1, 997
/*
* YOUR CODE GOES HERE:
* (1) Read an input csv line from stdin
* (2) Parse csv line into appropriate fields
* (3) Take action based on input type:
* - Check-in or check-out a patient with a given ID
* - Add a new health data type for a given patient
* - Store health data in patient record or print if requested
* (4) Continue (1)-(3) until EOF
*/
/* A new struct to hold all of the values from the csv file */
typedef struct {
int iD;
char *time[MAXTIME + 1];
int value;
int type;
}csv_input;
/* Declare an instance of the struct, and assign pointers for its values */
csv_input aLine;
int *idptr;
char timeval[MAXTIME + 1];
int *valueptr;
int *typeptr;
/*Note: because the time char is already a pointer, I did not make another one for it but instead dereferenced the pointer I was given */
idptr = &aLine.iD;
int j; /* iterator variable */
for(j; j < MAXTIME; j++){
*aLine.time[j] = timeval[j];
}
valueptr = &aLine.value;
typeptr = &aLine.type;
/* Get the Patient ID */
*idptr = getchar();
printf("%c", aLine.iD); /* a test to see if my pointers worked and the correct value was read */
/*Skip the first comma */
int next;
next = getchar();
/* get the timestamp */
int i;
for(i = 0; i < MAXTIME; i++)
{
while ((next = getchar()) != ',')
{
timeval[i] = next;
//printf("%s", aLine.time[i]);
}
}
First:
int j; /* iterator variable */
for(j; j < MAXTIME; j++){
You need to set j to some value, j=0 makes sense. Without this you're accessing an array with an uninitialized value and you're going to get UB with that.
Second:
/*Note: because the time char is already a pointer,
No, time is an array of pointers to characters, there is a difference there.
This line:
*aLine.time[j] = timeval[j];
won't work because, for one thing, of your statement but instead dereference the pointer I was given is making an incorrect assumption. Yes, you were given an array of pointers, but they don't point to anything, they are uninitialized and as such you can't deference them until you initialize them to a valid non-NULL value.
I think you were trying to do something like this:
aLine.time[j] = &timeval; //set the pointer to the local static array
but that's only going to work in the local function scope. It'd be better if you malloc to your array of pointers.
char *time[MAXTIME + 1];
this is an array of pointers (pointer to char array) and not an array of chars
The crash come from this line
*aLine.time[j] = timeval[j];
Because as I said aLine.time[j] is a pointer and you have not allocated memory for this pointer before filling its content
This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
(C) realloc array modifies data pointed by items
Hello,
A nice weird bug I feel like sharing ;-) Requires some preliminary explanations:
First, I have a type of strings PString which hold their size (and a hash value), followed by a flexible array member with the bytes. Here is the type and kind of constructor (the printfl statement at the end is debug):
typedef struct {
size_t size;
uint hash;
char bytes[];
} PString;
// offset from start of pstring struct to start of data bytes:
static const size_t PSTRING_OFFSET = sizeof(size_t) + sizeof(uint);
PString * pstring_struct (string str, size_t size, uint hash) {
// memory zone
char *mem = malloc(PSTRING_OFFSET + size * sizeof(char));
check_mem(mem);
// string data bytes:
memcpy(mem + PSTRING_OFFSET, str, size);
mem[PSTRING_OFFSET + size] = NUL;
// pstring struct:
PString * pstr = (PString *) mem;
pstr->size = size;
pstr->hash = hash;
printfl("*** str:'%s' (%u) --> pstr:'%s' (%u) 0x%X",
str, size, pstr->bytes, pstr->size, pstr); ///////////////////////
return pstr;
}
[Any comment on this construction welcome: I'm not sure at all to do things right, here. It's the first time I use flexible array members, and I could not find exemples of using them in allocated structs.]
Second, those pstrings are stored in a string pool, meaning a set implemented as hash table. As usual, "buckets" for collisions (after hash & modulo) are plain linked lists of cells, each holding a pstring pointer and a pointer to next cell. The only special detail is that the cells themselves are stored in an array, instead of beeing allocated anywhere on the heap [1]. Hope the picture is clear. Here is the definition of Cell:
typedef struct SCell {
PString * pstr;
struct SCell * next;
} Cell;
All seemed to work fine, including a battery of tests of the pool itself. Now, when testing a pstring routine (search), I noticed a string changed. After some research, I finally guessed the problem is related to pool growing, and endly could reduce the issue exactly around the growing of the array of cells (so, well before redistributing cells into lists). Here is the lines of debug prints around this growing, with copy of the show_pool routine producing the output (just shows the strings), and the output itself:
static void pool_grow (StringPool * pool, uint n_new) {
...
// Grow arrays:
show_pool(pool); /////////////////////
pool->cells = realloc(pool->cells, pool->n_cells * sizeof(Cell));
check_mem(pool->cells);
show_pool(pool); ////////////////////
...
static void show_pool (StringPool * pool) {
if (pool->n == 0) {
printfl("{}");
return;
}
printf("pool : {\"%s\"", pool->cells[0].pstr->bytes);
PString * pstr;
uint i;
for (i = 1; i < pool->n; i++) {
pstr = pool->cells[i].pstr;
printf(", \"%s\"", pstr->bytes);
}
printl("}");
}
// output:
pool : {"", "abc", "b", "abcXXXabcXXX"}
pool : {"", "abc", "b", "abcXXXabcXXXI"}
As you can see, the last string stored has an additional byte 'I'. Since in the meanwhile I'm just calling realloc, I find myself a bit blocked for further debugging; and thinking hard does not help in throwing light on this mystery. (Note that cells just hold pstring pointers, so how can growing the array of cells alter the string bytes?) Also, I'm bluffed by the fact there seems to be a quite convenient NUL just after the mysterious 'I', since printf halts there.
Thank you.
Can you help?
[1] There is no special reason for doing that here, with a string pool. I usually do that to get for free an ordered set or map, and in addition locality of reference. (The only overhead is that the array of cells must grow in addition to the array of buckets, but one can reduce the number of growings by predimensioning.)
Since size doesn't include the null terminator,
mem[PSTRING_OFFSET + size] = NUL;
is invalid. Every other issue stems from this.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
So, I'm a C# guy trying my hand at learning C. As a first (personal) project I am attempting to write a basic coordinate geometry library.
Question: Is it again best C programming practices to allocate memory on the heap behind the scenes instead of letting the programmer who is targeting the library do it?
For example, my 'point' struct & related methods:
point.h
/* A basic point type. */
typedef struct point
{
float x;
float y;
float z;
char *note;
}point;
/* Initializes a basic point type. [Free with free_point method] */
point *create_point(float pos_x, float pos_y, float pos_z, char *_note);
/* Frees a point type. */
void free_point(point *_point);
/* Finds the midpoint between two points. */
point *midpoint(point *pt1, point *pt2);
point.c
#include "point.h"
/* Initializes a basic point type. [Free with free_point method] */
point *create_point(float pos_x, float pos_y, float pos_z, char *_note)
{
point *p;
size_t notelen = strlen(_note);
p = (point*)malloc(sizeof(point));
p->x = pos_x;
p->y = pos_y;
p->z = pos_z;
p->note = (char*)calloc(notelen + 1, sizeof(char));
strcpy_s(p->note, notelen + 1, _note);
return p;
}
/* Frees a point type. */
void free_point(point *_point)
{
free (_point->note);
free (_point);
}
/* Creates a midpoint between two points. */
point *midpoint(point *pt1, point *pt2)
{
float mid_x = (pt1->x + pt2->x) * 0.5f;
float mid_y = (pt1->y + pt2->y) * 0.5f;
float mid_z = (pt1->z + pt2->z) * 0.5f;
point *p = create_point(mid_x, mid_y, mid_z, "Midpoint");
return p;
}
Notice that I creating the struct 'point' on the heap FOR whoever implements/uses my lib (in all honesty, this project is just for me and for learning, nevertheless...) via the create_point() method. Is this poor practice? It feels like I am forcing the user into programming a certain way. Same goes with the midpoint() method. Again, you must use pointers to a 'point' struct.
I was unable to find exact questions regarding C library design on SO, but please point me in the right direction if applicable.
Thanks.
It's preference, really. I usually subscribe to letting the user allocate the memory for the object however they wish, and then initializing the members for them.
/* here a non-zero return value might indicate if for example
* we failed to allocate memory for note */
int point_init(struct point* p, int x, int y, char* note)
{
/* ... */
}
/* usage: */
struct point p;
if (point_init(&p, 1, 2, "hello")) {
/* error */
}
This gives the user the option to do things like allocate an array of points that are adjacent in memory, instead of keeping track of an array of pointers to points:
struct point mypoints[NUM_POINTS];
for(size_t i = 0; i < NUM_POINTS; ++i) {
point_init(&mypoints[i], ...);
}
EDIT:
If you want to use the Opaque Pointer strategy to hide the members of your structure from the library user, you will need to allocate the memory for them using the method you described. That's certainly a huge benefit for allocating the structure in your library.
Best practice is to code the library in such a way that the programmer can do what's fastest, since that is a forte of C. For example, the programmer might know that tens of thousands of these point structs will be needed and for the sake of keeping future accesses local might prefer to allocate all the structs in one block of memory. If your library lets the programmer pass pointers in for structs to be initialized, then he can do this. But if you insist on allocating the memory for him, he can't.