Getting and unsigned char's size

Thread Starter

asilvester635

Joined Jan 26, 2017
73
Why is this giving me a problem? How can I fix it? I'm basically passing a size containing a value of 2 to the makeArray function. Then I make an unsigned char* array Inside the makeArray function, fill its first two subscript, then return that array to main.cc.

Error:
main.cc:11:16: error: cannot initialize a variable of type 'unsigned char' with


an rvalue of type 'unsigned char *'

unsigned char array = makeArray(size);

^ ~~~~~~~~~~~~~~~

1 error generated.

make: *** [main.o] Error 1

make: *** [main.o] Error 1

main.cc
Code:
    int size = 2;

    unsigned char array = makeArray(size);

    for (int i = 0; i < size; i++) {
        printf("%d\n", array[i]);

    } // end of for loop

functions.cc
Code:
unsigned char* makeArray(int size) {
    unsigned char* array = new unsigned char[size];

    // fill in the array
    array[0] = '1';
    array[1] = '0';

    // return array
    return array;

} // end of makeArray
 
Last edited:

WBahn

Joined Mar 31, 2012
32,823
The code you posted is not the same code that produced the error. The error message includes:

unsigned char array = makeArray(size);

But the code you posted contains:

char* array = makeArray(size);

How can a mechanic tell you what is wrong with your car if you take him your wife's car to look at?
 

Thread Starter

asilvester635

Joined Jan 26, 2017
73
The code you posted is not the same code that produced the error. The error message includes:

unsigned char array = makeArray(size);

But the code you posted contains:

char* array = makeArray(size);

How can a mechanic tell you what is wrong with your car if you take him your wife's car to look at?
Hey, I updated it. It should be the correct code. Now, what is causing this code to give me an error? I'm returning a pointer to an unsigned char array to an unsigned char array back in main.cc. I've tried many different styles of receiving the pointer in main.cc.
 

WBahn

Joined Mar 31, 2012
32,823
Hey, I updated it. It should be the correct code. Now, what is causing this code to give me error? I'm returning a pointer to an unsigned char array to an unsigned char array back in main.cc.
How about if you changed your code to this:

unsigned char fred = makeArray(size);

unsigned char array = ....;

is NOT declaring an array of type unsigned char. It is declaring a single variable of type unsigned char that just happens to be named "array".
 

Thread Starter

asilvester635

Joined Jan 26, 2017
73
How about if you changed your code to this:

unsigned char fred = makeArray(size);

unsigned char array = ....;

is NOT declaring an array of type unsigned char. It is declaring a single variable of type unsigned char that just happens to be named "array".
Okay, I get what you're saying. I see that array is just another unsigned char variable and not an actual array. I made it an array by attaching the [] in front of the array. Though I'm still getting an error below. unsigned char[size] is not assignable. Then how I am I suppose to receive the pointer??

ERROR:
main.cc:13:8: error: array type 'unsigned char *[size]' is not assignable


array = makeArray(size);

~~~~~ ^

1 error generated.

make: *** [main.o] Error 1

Code:
    int size = 2;

    unsigned char* array[size];

    array = makeArray(size);


    for (int i = 0; i < size; i++) {
        printf("%s\n", array[i]);

    } // end of for loop
 

WBahn

Joined Mar 31, 2012
32,823
When you declare an array using

int fred[32];

The identifier 'fred' is a pointer constant. You can't change it.

If you want to declare a pointer to an array of unsigned char, then read the error message you are getting and do what it says:

main.cc:11:16: error: cannot initialize a variable of type 'unsigned char' with an rvalue of type 'unsigned char *'

It says you are returning a value of "unsigned char *" and that you can't store that in a variable of type "unsigned char". Well, how about storing it in a variable of type "unsigned char *" instead?

Look at the type of the variable "array" in your makeArray() function. Since that IS the variable you are returning from your function, wouldn't it make sense that the variable you are storing that value in should be of the same type?

Remember that recommendation I made about perhaps actually reading a textbook on C/C++ programming or working through some online tutorials instead of having to put up with the glacial pace of asking questions and trying to learn via two-way exchanges about each error and warning and issue you run up against? This is a good example. I doubt that there is a text out there that doesn't cover passing and returning arrays and pointers to array in significant depth.


 

djsfantasi

Joined Apr 11, 2010
9,237
Never mind online tutorials.

But in this case, you have to read the error messages and learn what they mean.

I found the problem after a quick google (and writing a test program to test my theories)

I am curious why you want to do this? You have never mentioned it.
 

Thread Starter

asilvester635

Joined Jan 26, 2017
73
Never mind online tutorials.

But in this case, you have to read the error messages and learn what they mean.

I found the problem after a quick google (and writing a test program to test my theories)

I am curious why you want to do this? You have never mentioned it.
I'm trying to learn things little by little. Ultimately I'm attempting to read a PPM image, which contains binary pixel data. I will read it with an unsigned char* pixel and write them onto another file.
 

WBahn

Joined Mar 31, 2012
32,823
I got it. I changed the portion where I fill in the array inside my makeArray function to the code below. I declared that the array is of size 2, but I never really initialized the last storage location array[2]. It works now but why does it let me initialize three slots inside the array when I only made it size 2? Aren't we overriding some other storage location? Possibly erasing a piece of memory (might be important data) and replacing it with another value using this code array[2] = '1';?
Yep. You are violating the array bounds and stomping on memory that belongs to something else. But C/C++ will happily let you do that. They assume that if you are using C/C++ that you are willing to accept the responsibility for doing your own bounds checking (and many, many other checks that many people don't do). In exchange, you get significantly more performance. The C language is about performance, not safety or reliability -- that makes it a pretty poor language for most people and most applications. But if you need performance, then it is hard to beat (in a high level language).
 

Thread Starter

asilvester635

Joined Jan 26, 2017
73
Yep. You are violating the array bounds and stomping on memory that belongs to something else. But C/C++ will happily let you do that. They assume that if you are using C/C++ that you are willing to accept the responsibility for doing your own bounds checking (and many, many other checks that many people don't do). In exchange, you get significantly more performance. The C language is about performance, not safety or reliability -- that makes it a pretty poor language for most people and most applications. But if you need performance, then it is hard to beat (in a high level language).
Thanks. I couldn't really make sense of the error message, but now that you've pointed it out, it was pretty obvious.
 

djsfantasi

Joined Apr 11, 2010
9,237
It's been a while since the TS has replied. However, I have an example that resolves his problem. This code compiles without errors and executes successfully. Please note that it is an Arduino C++ variant program, However, it illustrates the concepts necessary for a successful implementation

Code:
#define halt while(-1){}

void setup() {
  Serial.begin(9600);
}

void main() {
  char* anArray=NULL; // define a pointer to the array
  unsigned int Size = 3; // value of the desired array to pass

  anArray = makeArray(Size); // create the array

  for (int i = 0; i <= Size; i++) { // print out the test
    Serial.println(anArray[i]);
  }

  Serial.println();
  halt;
  // normally, array memory should be deleted around here
}

// makearray function
char* makeArray(int mySize) { // function returns a pointer

  char* myArray = new char[mySize]; // create the array

  for (int i = 0; i <= mySize; i++) { // fill the array with test values
    myArray[i] = 65+ i;
  }
  return myArray; // return the pointer to the allocated array
}
The first major difference between your code and the example, is that instead of defining a local array in main with the statement "unsigned char* array[size];", we ask what is needed. We do not need to define an array in main(); we need to define a pointer to an array. You would think we would need an array, but we are defining the array in the function makearray and returning a pointer to this array, Since we used the new function to allocate the array, it will persist beyond the scope of the function, i.e., the only way to "lose" the array is to deallocate it.

Thus, the function makearray returns a char pointer, the same as the pointer type defined in the main.
All variable types now match.

In summary, this is the technique I used to get this to work. Do not define an array in main(). Only define a pointer of the array type desired AND initialize it to NULL. Create the array in the function and return the pointer to the array, which is the array name without any indices. Set the pointer defined in main() to the returned value. Hence, main() will now reference the array memory created in the function.

Get it, @asilvester635 ?
 
Last edited:
Top