Array assignment in C - c

If I have defined this:
typedef char word[30];
typedef struct {
int num;
word group[30];
} paragraph;
And then in the body:
int
main(int argc, char **argv) {
paragraph p;
word w = "BLA";
return 0;
}
How do I assign w in the array p and then printf w in terms of p
I know this is wrong but e.g.:
p[][1] = w;
printf("%s", p[][1]);
Pleas help a noob out

Arrays are not assignable. Either initialize your array to the proper size and set each element as needed or store a pointer instead.

Assuming you really intend to use the flexible array member introduced in C99, you would need to write code like:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef char word[30];
typedef struct {
int num;
word group[];
} paragraph;
int main(void)
{
paragraph *p = malloc(sizeof(*p) + 1 * sizeof(word));
word w = "BLA";
strcpy(p->group[0], w);
printf("Word: %s\n", p->group[0]);
free(p);
return 0;
}
That's modestly tricky code. Avoid using flexible array members until you understand what all this is doing. Until then, make the group member of the paragraph into a word:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef char word[30];
typedef struct {
int num;
word group;
} paragraph;
int main(void)
{
paragraph p;
word w = "BLA";
strcpy(p.group, w);
printf("Word: %s\n", p.group);
return 0;
}
The key point remains that you cannot directly assign arrays and need to use strcpy() or a relative with strings, and memmove() or perhaps memcpy() with other types. You can assign structures that contain arrays in general (though you can't do that with structures containing a flexible array member), but that's because you can do structure assignment and it is coincidental that the structure contains an array.
BUT for word group, if you put group[30], how does that affect the rest of the code?
Here's code that does as you ask:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef char word[30];
typedef struct
{
int num;
word group[30];
} paragraph;
int main(void)
{
paragraph p;
word w = "BLA";
strcpy(p.group[0], w);
printf("Word: %s\n", p.group[0]);
return 0;
}
Under this structure, assuming sizeof(int) == 4, you would find that sizeof(paragraph) == 904 because you've declared an array of 30 words, and each word is an array of 30 characters. This structure would allow you to add multiple words to the paragraph (and most paragraphs that I write most certainly contain more than one word!). You still have to use strcpy() to copy the word from w to an element of p.group:
int main(void)
{
paragraph p;
word w = "BLA";
strcpy(p.group[0], w);
strcpy(p.group[1], "Porcupine");
strcpy(p.group[2], "Elephant");
p.num = 3;
printf("Word: %s\n", p.group[0]);
printf("Paragraph:");
for (int i = 0; i < p.num; i++)
printf(" %s", p.group[i]);
putchar('\n');
return 0;
}
While it isn't wrong to use a typedef like word, it isn't something I'd normally do. It can all too easily lead to more confusion than enlightenment. It could also lead to wasted memory if most of your words are significantly fewer than 29 characters long. (The onus is on you to ensure that you do not store words longer than 29 characters (plus the terminating null byte) in the p.group array elements.) OTOH, the overhead of memory allocation with 64-bit software could easily render the wasted space for a single word moot.

Related

Automatic generation of struct printing function in C

I have many programs where structs are defined. And each time, I have to create a function to print the members. For example,
typedef struct {
char name[128];
char address[1024];
int zip;
} myStruct;
void printMyStruct(myStruct myPeople) {
printf("%s\n",myPeople.name);
printf("%s\n",myPeople.address);
printf("%d\n",myPeople.zip);
}
int main()
{
myStruct myPeople={"myName" , "10 myStreet", 11111};
printMyStruct(myPeople);
}
I know that reflection is not supported in C. And so, I write these printing functions for each struct I defined.
But, I wonder if it exists any tricks to generate automatically these printing functions. I would understand that I have to modify a little bit these functions. But, if a part of the job is done automatically, it would be great.
(This example is simple, sometimes struct are nested or I have array of structs or some fields are pointers, ...)
You can of-course print structs, but expect a lot of non-readable output:
#include <stdio.h>
#include <ctype.h>
struct example {
int x;
int y;
char c;
};
#define NOT_PRINTABLE "Not Printable"
void print_structure(const char *structure, size_t size) {
for (size_t i = 0; i < size; i++) {
printf("%ld)\t%.2X: %.*s\n", i, structure[i],
(isprint(structure[i]) ? 1 : sizeof(NOT_PRINTABLE) - 1),
(isprint(structure[i]) ? &structure[i] : NOT_PRINTABLE));
}
}
int main(int argc, char **argv) {
struct example a;
a.x = 5;
a.y = 6;
a.c = 'A';
print_structure((char *)&a, sizeof(struct example));
return 0;
}
But the issue is that, it will print the structs as it is represented in memory. So 4 byte (32 bit) integer 1 will be represented with 4 bytes, not the char '1'.
And due to the way pointers work, you cannot make out if a member is a pointer or a non-pointer.
Another issue is that structures have padding to help with alignment, and better/efficent use of memory. So you would see a lot of 0x00 in the middle.
Remember that C is a compiled language.
let's consider to use https://copilot.github.com/. it's great.
this is what i have with copilot
typedef struct {
char name[128];
char address[1024];
int zip;
} myStruct;
//print struct myStruct >> auto generate by codepilot after you type a comment `print struct myStruct`
void printStruct(myStruct *s) {
printf("name: %s\n", s->name);
printf("address: %s\n", s->address);
printf("zip: %d\n", s->zip);
}

Initialize array within a structure

In my project, I am asked to store my 2D array of words in a dynamic data structure, then use them in other functions for other purposes, but I am confused how should I do this. I do understand, how to name them separately like:
#include <stdio.h>
#include <stdlib.h>
typedef struct Names {
char *name[5];
} Names;
void func(Names y) {
printf("%s\n%s", y.name[0], y.name[1]);
}
int main()
{
Names y;
y.name[0] = "John";
y.name[1] = "Luke";
func(y);
return 0;
}
But what if I wanted to do this as a 2d array. So normally I would do char names[][10] = {"John", "Luke", etc..}; but how do I store that in a struct? I mean if I did
#include <stdio.h>
#include <stdlib.h>
typedef struct Names {
char *name[5][10];
} Names;
void func(Names y) {
printf("%s\n%s", y.name[0], y.name[1]);
}
int main()
{
Names y;
y.name[][10] = {"John", "Luke"};
func(y);
return 0;
}
That would just give errors and make no sense.
This is the official way to do it (see Nested initialization in: Struct and union initialization):
#include <stdio.h>
typedef struct Names {
const char *name[2][2];
} Names;
void func(Names* y) {
printf("%s, %s\n", y->name[0][0], y->name[0][1]);
printf("%s, %s\n", y->name[1][0], y->name[1][1]);
}
int main()
{
Names y = { .name={{"John", "Luke"}, {"Jack", "Jim"}}};
func(&y);
return 0;
}
Also the following works for backwords-compatibility reasons:
#include <stdio.h>
typedef struct Names {
const char *name[2][2];
} Names;
void func(Names* y) {
printf("%s, %s\n", y->name[0][0], y->name[0][1]);
printf("%s, %s\n", y->name[1][0], y->name[1][1]);
}
int main()
{
Names y = {"John", "Luke", "Jack", "Jim"};
func(&y);
return 0;
}
The above is managing string constants stored in const char pointers, for variable strings of up to 9 chars lentgh with a trailing zero-terminator, something like the following will be possible (I made compile-time constants for 5 and 9):
#include <stdio.h>
enum {
NAME_COUNT = 5,
NAME_LENGTH = 9
};
typedef struct Names {
char name[NAME_COUNT][NAME_LENGTH+1];
} Names;
void func(Names* y) {
for (int i=0; i<NAME_COUNT; ++i) {
printf("%s\n", y->name[i]);
}
}
int main()
{
Names y = { .name={"John", "Olivia", "Luke", "Mary", "Jane" }};
func(&y);
return 0;
}
I think what you may be missing is the fact that char *name[5]; is not really a 2d array of words, it's an array of 5 pointers to char, you then make the two first pointers of that array point to two string literals. In the second expression you have a 5 by 10 2d array of pointers to char, each one of these pointer can also point to its own string literal, so naturally the expression:
y.name[][10] = {"John", "Luke"};
Is not correct for several reasons, the compiler needs to know both dimensions of the array to know to which pointer you want to assign the string literal, knowing this you'll note that the assigned expression makes little sense.
Example:
y.name[1][1] = "John";
Here you would assign the string literal "John" to the pointer located in the index [1][1] of the array of pointers.
Now, if you want an array of 5 words each one containing 10 characters, including the null byte you would simply use:
char name [5][10]
Note that in this configuration you can't simply assign the strings, you'll need to copy them using somenthing like strcpy.
strcpy(y.name[0], "John");

What am I doing wrong in passing a struct around in C?

So I am working on a project in C that requires that I pass pointers to a struct into functions. The project is structured as follows:
struct structName {
unsigned short thing2;
char thing1[];
};
void function_1(struct structName *s) {
strcpy(s->thing1, "Hello");
printf("Function 1\n%s\n\n", s->thing1); // prints correctly
}
void function_2(struct structName *s) {
// can read thing2's value correctly
// thing1 comes out as a series of arbitrary characters
// I'm guessing it's an address being cast to a string or something?
printf("Function 2\n%s\n\n", s->thing1); // prints arbitrary characters ('É·/¨')
}
int main() {
struct structName s;
function_1(&s);
printf("Main\n%s\n\n", s.thing1);
function_2(&s);
printf("Main 2\n%s\n\n", s.thing1);
}
This code outputs the following:
Function 1
Hello
Main
Hello
Function 2
É·/¨
Main 2
É·/¨
Obviously, the program has more than just what I've written here; this is just a simplified version; so if there's anything I should check that might be causing this let me know. In all honesty I reckon it's probably just a stupid rookie error I'm making somewhere.
[EDIT: Seems like s.thing1 is being mutated in some way in the call to function_2(), since the odd value is replicated in main() - I should point out that in my program the printf()s are located right before the function call and in the first line of the function, so there's no chance that it's being written to by anything I'm doing. I've updated the example code above to show this.]
Thanks in advance!
The structure contains a flexible member at its end, if you declare a static object with this type, the length of this member will be zero, so strcpy(s->thing1, "Hello"); will have undefined behavior.
You are supposed to allocate instances of this type of structure with enough extra space to handle whatever data you wish to store into the flexible array.
Here is an example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct pstring {
size_t length;
char data[];
} pstring;
pstring *allocate_pstring(const char *s) {
size_t length = strlen(s);
pstring *p = malloc(sizeof(*p) + length + 1);
if (p != NULL) {
p->length = length;
strcpy(p->data, s);
}
return p;
}
void free_pstring(pstring *p) {
free(p);
}
int main() {
pstring *p = allocate_pstring("Hello");
printf("Main\n%.*s\n\n", (int)p->length, p->data);
free_pstring(p);
return 0;
}

How do I return a struct (from a function) containing an array with the correct elements in that array?

I'm making a program that returns a struct containing an array, but the elements in the array are completely wrong. I keep searching for an answer on this site, Google, and even Bing and nothing. The best I can find are answers like this:
Functions can't return arrays in C.
However, they can return structs. And structs can contain arrays...
from How to make an array return type from C function?
Now, how do I fix this without the use of pointers?
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <ctype.h>
struct Codes{
int as;
int a[];
};
struct Codes create(int as){
int a[as];
for(int j = 0;j<as;j++)
a[j]=j+1;
struct Codes c;
c.as = as;
c.a[c.as];
for(int i=0; i<as; i++)
c.a[i] = a[i];
for(int i=0; i<as; i+=1)
printf("%d \n", c.a[i]);
return c;
}
int main(int argc, char **argv) {
struct Codes cd;
int as = 4;
cd = create(as);
for(int i=0; i<4; i+=1)
printf("%d \n", cd.a[i]);
}
Actual output:
1
2
3
4
0
0
2
-13120
Expected output:
1
2
3
4
1
2
3
4
structs with flexible value are not meant to be manipulated by value, only by pointer.
You cannot return a struct with a flexible member by value, because C does not know how many items it needs to allocate to the return value, and how many bytes it needs to copy.
Allocate your struct in dynamic memory using malloc of sufficient size, copy your data into it, and return a pointer to the caller:
struct Codes *c = malloc(sizeof(struct Codes)+as*sizeof(int));
c->as = as;
for (int i = 0 ; i != as ; i++) {
c->a[i] = i+1;
}
return c;
Change your function to return a pointer; make sure the caller frees the result.
In your function, struct Codes create(int as), the struct Codes c; is allocated on the stuck, so the memory is no longer valid once the function returns...
...It is true that the core struct is copied in the return value... but the variable array length c.a isn't part of the struct (it's a memory "trailer" or "footer") and isn't copied along with the return value.
Either:
allocate the struct and pass it to a struct Codes create(struct Codes *dest, int as) function; OR
make the struct array fixed in size struct Codes{ int as; int a[4]; };
Good luck.

Strange Struct Array Printing Error in C

Hey all I'm having some trouble diagnosing the reason for an error in printing an array of structures in C.
In a separate header file (call it header.h) I have the following typedef'd structure:
typedef struct instruction prog;
struct instruction{
char kind;
char op[4];
};
For my main programing task I want to read from a file a series of what are supposed to be instructions consisting of a type character (the variable kind above) and an instruction consisting of four integers (listed as op above). Examples include R 1004 E 1008, etc. I can read the data in just fine but it seems to be storing things improperly. I wrote the following test code to see if I could find the error but I was still getting the same issue. My goal is to store these as an array of instructions where, using the parlance of the code below, mem[i].kind = 'R' and mem[i].op =1004`.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <stdbool.h>
#include "header.h"
void memFill(prog *P, int x);
void memPrint(prog *P, int x);
int main(){
prog mem[10];
memFill(&mem[0], 10);
memPrint(&mem[0], 10);
return 0;
}
void memFill(prog *P, int x){
char *v = "1004";
for(int i = 0; i< x; i++){
P->kind = 'R';
strcpy(P->op, v);
P++;
}
}
void memPrint(prog *P, int x){
for(int i = 0; i <x; i++){
printf("%c %s\n",P->kind, P->op);
P++;
}
}
This is giving me output that looks like this:
R 1004R1004R1004R1004R1004R1004R1004R1004R1004R1004
R 1004R1004R1004R1004R1004R1004R1004R1004R1004
R 1004R1004R1004R1004R1004R1004R1004R1004
R 1004R1004R1004R1004R1004R1004R1004
R 1004R1004R1004R1004R1004R1004
R 1004R1004R1004R1004R1004
R 1004R1004R1004R1004
R 1004R1004R1004
R 1004R1004
R 1004
The reason this is weird is that identical pointer arithmetic has given just fine results with a similar structure. What's going on here? What am I missing?
Buffer overflow on char op[4], then Undefined_behavior
To be able to store "1004" it have to be 5 bytes long to have space for NULL terminator.
struct instruction{
char kind;
char op[5];
};
Literal string "1004" is '1', '0', '0', '4', '\0'
You forgot to give space for the string ending null.
Fix your struct declaration to this:
struct instruction{
char kind;
char op[5];
};
And it will work.
You can also simplify declaration this way:
typedef struct instruction{
char kind;
char op[5];
} prog;

Resources