C How to print arrayList with multiple vectors inside?

Thread Starter

AstolfoMuniz

Joined Oct 4, 2022
6
Hello. I have the following code and I wanna to print all chars in each vector, but Idon´t know how to (line 12):

Simple vector list:
#include <stdio.h>

const int messageOne[] = {0x31, 0x30};
const int messageTwo[] = {0x35, 0x36, 0x37, 0x38};
const int messageTree[] = {0x41, 0x42, 0x43, 0x45, 0x44, 0x54};
const int **messageList = {messageOne, messageTwo, messageTree};
const int vectorSize = (sizeof(messageList) / sizeof(messageList[0]));

int main() {
    for (int i = 0; i <= vectorSize; i++) {
        for (int j = 0; j <= sizeof(messageList) / sizeof(messageList[0]); j++) {
            printf("%d %d %c ", i, j, messageList);
        }
        printf("\n");
    }
    return 0;
}
The expected value would be:
10
5678
ABCDEF

Can someone help me?
 
Last edited:

WBahn

Joined Mar 31, 2012
32,703
You have the following expression twice:

sizeof(messageList) / sizeof(messageList[0])

Once when you use:

vectorSize = (sizeof(messageList) / sizeof(messageList[0]))

and again when you use:

j <= sizeof(messageList) / sizeof(messageList[0])

Yet you seem to be expecting different results in each case?

Then think about:

printf("%d %d %c ", i, j, messageList)

Is the variable message an integer whose value is character code? Or is it, as defined, a pointer to a pointer to and integer (i.e., an address)?
 

Thread Starter

AstolfoMuniz

Joined Oct 4, 2022
6
Thanks for the answer.

I put it twice because it was my last attempt before posting the message to the forum.
I tried in several ways, but I didn't get the expected result.
The current result is:
0 0 0 1
1 0 1 1

The another example that I made is:

Code:
#include <stdio.h>

const char messageOne[] = {0x31, 0x30};
const char messageTwo[] = {0x35, 0x36, 0x37, 0x38};
const char messageTree[] = {0x41, 0x42, 0x43, 0x45, 0x44, 0x45};
const char **messageList = {messageOne, messageTwo, messageTree};
const int vectorSize = (sizeof(messageList) / sizeof(messageList[0]));

int main() {
    for (int i = 0; i <= vectorSize; i++) {
        printf("%d - %c, ", i, (char) &messageList[i]);
    }
    return 0;
}
But the result was:
0 -, 1 - ►,

I don't know how to proceed, Im lost!!!
 
Last edited:

WBahn

Joined Mar 31, 2012
32,703
Is there a specific reason that you can't NUL terminate your three character arrays? That would make like a LOT simpler.
 

Thread Starter

AstolfoMuniz

Joined Oct 4, 2022
6
I cant Null terminator, because this words came from a panel... The original message is different!

I got a progress. Using the following code, i get the first char of each vector:

Code:
#include <stdio.h>

const char messageOne[] = {0x31, 0x30};
const char messageTwo[] = {0x35, 0x36, 0x37, 0x38};
const char messageTree[] = {0x41, 0x42, 0x43, 0x45, 0x44, 0x45};
const char *messageList[] = {&messageOne, &messageTwo, &messageTree};
const int vectorSize = (sizeof(messageList) / sizeof(messageList[0]));

int main() {
    for (int i = 0; i <= vectorSize; i++) {
        for (int j = 0; j< vectorSize; j++) {
            printf("%c", *messageList[i]);
        }
        printf("\n");
    }
    return 0;
}
The result is:
111
555
AAA

Now I need to know, how to do the sequence.
 
Last edited:

michael8

Joined Jan 11, 2015
472
The loop which tries to print the messages doesn't have any
way of knowing how long each string/message is.

So it's "impossible" to print them correctly.

Somehow you need to pass the length of each message (in addition to
the address of each message) to the print loop.

The standard way in C is to put a \0 (byte of 0) at the end of each string.

Alternatives include a separate array matching the messagelist which
has the length of it's related string or make the first byte of each
message hold the length.

in C:
const int messageOne[] = {0x31, 0x30}; is 0x31, 0x30 -> 2 integers long
const char messageOne[] = "31"; is 0x31, 0x30, 0x00 -> 3 bytes long
 

WBahn

Joined Mar 31, 2012
32,703
Could you give me an example?
The NUL character is, from a programmer's perspective, treated as the value zero. So if you tack that onto the end of your array, you have an array of character codes that ends with a NUL character. This is better known as a "NUL-terminated string" and the printf() function (as well as many other functions) knows how to deal with these.

Code:
const char messageOne[] = {0x31, 0x30, 0x00};
printf("%s\n", messageOne;
It sounds like you need to learn how to tease information out of your program (or how to use a debugger), since it appears that you are just making desperate changes to your program hoping that, at some point, something good happens.

What do you expect (or at least want) the value of

(sizeof(messageList) / sizeof(messageList[0])

to be?

I'm guessing you want it to be the number of messages in the messageList array.

But is it?

Have you looked at it by simply adding a print statement such as:

printf("vectorSize: %i\n", vectorSize);

If that doesn't print what you expected, then you have a learning opportunity. Start tracking down what is actually going on until you understand why it is printing what it is.
 

WBahn

Joined Mar 31, 2012
32,703
One very subtle thing that few C programmers know is that there is a difference between

int myArray1[] = {1, 2, 3, 4, 5, 6, 7, 8};
int *myArray2 = {1, 2, 3, 4, 5, 6, 7, 8};

print out the sizeof() each and see if you can explain the difference (or at least what each number represents the size of).

This distinction has important implications for your code.
 
Last edited:

michael8

Joined Jan 11, 2015
472
Also look at the difference between:

const int messageTree[] = {0x41, 0x42, 0x43, 0x45, 0x44, 0x54};
const char messageTree[] = {0x41, 0x42, 0x43, 0x45, 0x44, 0x54};
 

Thread Starter

AstolfoMuniz

Joined Oct 4, 2022
6
In fact, the final value is the same!
I'll transform this array into a String (char array), for example {0x41, 0x42, 0x43, 0x44, 0x45, 0x46} into "ABCDEF" when sending via Serial Port.
So that's not my biggest concern. I want to know is how to access in a list, a specific array, being traversed by the loop.
The code must be
Code:

char messageOne[] = {0x31, 0x30, 0x00, 0x00, 0x00, 0x00};
char messageTwo[] = {0x35, 0x36, 0x37, 0x38, 0x00, 0x00};
char messageTree[] = {0x41, 0x42, 0x43, 0x44, 0x45, 0x46};
char (*messageList[]) = {messageOne, &messageTwo, &messageTree};
or
Code:

int messageOne[] = {0x31, 0x30, 0x00, 0x00, 0x00, 0x00};
int messageTwo[] = {0x35, 0x36, 0x37, 0x38, 0x00, 0x00};
int messageTree[] = {0x41, 0x42, 0x43, 0x44, 0x45, 0x46};
int (*messageList[]) = {messageOne, &messageTwo, &messageTree};
Thanks.
 

WBahn

Joined Mar 31, 2012
32,703
In fact, the final value is the same!
The final value of what is the same?

Not the examples you were asked to run.

Code:
#include <stdio.h>

int main() 
{
    int myArray1[] = {1, 2, 3, 4, 5, 6, 7, 8};
    int *myArray2 = {1, 2, 3, 4, 5, 6, 7, 8};
    const int messageTree1[] = {0x41, 0x42, 0x43, 0x45, 0x44, 0x54};
    const char messageTree2[] = {0x41, 0x42, 0x43, 0x45, 0x44, 0x54};
    
    printf("sizeof(myArray1) = %i\n", sizeof(myArray1));
    printf("sizeof(myArray2) = %i\n", sizeof(myArray2));
    printf("sizeof(messageTree1) = %i\n", sizeof(messageTree1));
    printf("sizeof(messageTree2) = %i\n", sizeof(messageTree2));

    return 0;
}
Produces:

Code:
sizeof(myArray1) = 32
sizeof(myArray2) = 8
sizeof(messageTree1) = 24
sizeof(messageTree2) = 6
Remember, the sizeof() operator always returns a value in bytes.

The variable 'myArray1' is defined as an array (using the square brackets), so the compiler KNOWS that it is an array and when you ask for its size, it returns the size required to store the array (which means that this must be determinable at compiler time). The array contains 8 elements and on the machine I ran this on an int requires 4 bytes, hence 32 bytes total.

The variable 'myArray2' is defined as a pointer to an int. So the compiler returns the amount of memory needed to store a pointer to an int, which is 8 bytes on most 64-bit machines. It doesn't matter how much memory is needed to store whatever is being pointed to, because it is returning the amount of memory needed to store the pointer itself.

I'll transform this array into a String (char array), for example {0x41, 0x42, 0x43, 0x44, 0x45, 0x46} into "ABCDEF" when sending via Serial Port.
So that's not my biggest concern. I want to know is how to access in a list, a specific array, being traversed by the loop.
In C, a char array is NOT a string UNLESS it is NUL-terminated. When you transmit it via the serial port, you can choose whether you transmit the NUL character or not. But if you want C functions like printf() to work correctly with a string, it MUST be properly NUL-terminated. If it appears to work like you wanted, it is because you got unlucky and the first byte of memory after the array just happen to have a zero stored there -- I say "unlucky" because it has led you into thinking you don't need the NUL-terminator, a conclusion that will come back to bite you.

The code must be
Code:

char messageOne[] = {0x31, 0x30, 0x00, 0x00, 0x00, 0x00};
char messageTwo[] = {0x35, 0x36, 0x37, 0x38, 0x00, 0x00};
char messageTree[] = {0x41, 0x42, 0x43, 0x44, 0x45, 0x46};
char (*messageList[]) = {messageOne, &messageTwo, &messageTree};
or
Code:

int messageOne[] = {0x31, 0x30, 0x00, 0x00, 0x00, 0x00};
int messageTwo[] = {0x35, 0x36, 0x37, 0x38, 0x00, 0x00};
int messageTree[] = {0x41, 0x42, 0x43, 0x44, 0x45, 0x46};
int (*messageList[]) = {messageOne, &messageTwo, &messageTree};
Thanks.
You are putting the value of 'messageOne' (which is a pointer to the first element in the array) into the list, but then the address where the following two array variables are stored.

It turns out that the C standard says that the address of an array (as opposed to the address of a pointer) is the same as the address of the first element in the array. So you would end up getting away with this, but it is very poor style. At least be consistent!

Your messageTree array in both cases is not NUL-terminated, so when you print it out (or do any other string-thing with it), the memory will be searched until it finds the first value that happens to be equal to zero.

Also, to be treated as strings, they must be char arrays.

Code:
int main() 
{
    const int messageTree1[] = {0x41, 0x42, 0x43, 0x45, 0x44, 0x54, 0x00};
    const char messageTree2[] = {0x41, 0x42, 0x43, 0x45, 0x44, 0x54, 0x00};
    
    printf("messageTree1: = \"%s\"\n", messageTree1);
    printf("messageTree2: = \"%s\"\n", messageTree2);

    return 0;
}
Produces:

Code:
messageTree1: = "A"
messageTree2: = "ABCEDT"
Because an int takes four bytes (on my machine with my compiler), 0x41 must be stored as a sequence of four bytes. Because I am using an Intel-based architecture, these values are stored in Little Endian, which means that the 0x41 comes first, followed by three bytes that are 0x00. As a result, when I print it out, I only get the A because the next byte in memory is interpreted as the string's NUL-terminator.
 
Top