Getting and unsigned char's size

Discussion in 'Programmer's Corner' started by asilvester635, Feb 16, 2017.

  1. asilvester635

    Thread Starter Member

    Jan 26, 2017
    68
    3
    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 (Text):
    1.  
    2.     int size = 2;
    3.  
    4.     unsigned char array = makeArray(size);
    5.  
    6.     for (int i = 0; i < size; i++) {
    7.         printf("%d\n", array[i]);
    8.  
    9.     } // end of for loop
    10.  

    functions.cc
    Code (Text):
    1.  
    2. unsigned char* makeArray(int size) {
    3.     unsigned char* array = new unsigned char[size];
    4.  
    5.     // fill in the array
    6.     array[0] = '1';
    7.     array[1] = '0';
    8.  
    9.     // return array
    10.     return array;
    11.  
    12. } // end of makeArray
    13.  
     
    Last edited: Feb 16, 2017
  2. WBahn

    Moderator

    Mar 31, 2012
    19,295
    5,234
    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?
     
  3. asilvester635

    Thread Starter Member

    Jan 26, 2017
    68
    3
    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.
     
  4. WBahn

    Moderator

    Mar 31, 2012
    19,295
    5,234
    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".
     
  5. asilvester635

    Thread Starter Member

    Jan 26, 2017
    68
    3
    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 (Text):
    1.  
    2.     int size = 2;
    3.  
    4.     unsigned char* array[size];
    5.  
    6.     array = makeArray(size);
    7.  
    8.  
    9.     for (int i = 0; i < size; i++) {
    10.         printf("%s\n", array[i]);
    11.  
    12.     } // end of for loop
    13.  
     
  6. WBahn

    Moderator

    Mar 31, 2012
    19,295
    5,234
    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.


     
  7. djsfantasi

    AAC Fanatic!

    Apr 11, 2010
    3,457
    1,228
    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.
     
  8. WBahn

    Moderator

    Mar 31, 2012
    19,295
    5,234
    It looks like just scratch code to try things out purely for the sake of learning the concepts.
     
  9. asilvester635

    Thread Starter Member

    Jan 26, 2017
    68
    3
    It works perfectly now. Thanks.
     
  10. asilvester635

    Thread Starter Member

    Jan 26, 2017
    68
    3
    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.
     
  11. WBahn

    Moderator

    Mar 31, 2012
    19,295
    5,234
    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).
     
  12. asilvester635

    Thread Starter Member

    Jan 26, 2017
    68
    3
    Thanks. I couldn't really make sense of the error message, but now that you've pointed it out, it was pretty obvious.
     
  13. djsfantasi

    AAC Fanatic!

    Apr 11, 2010
    3,457
    1,228
    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 (Text):
    1.  
    2. #define halt while(-1){}
    3.  
    4. void setup() {
    5.   Serial.begin(9600);
    6. }
    7.  
    8. void main() {
    9.   char* anArray=NULL; // define a pointer to the array
    10.   unsigned int Size = 3; // value of the desired array to pass
    11.  
    12.   anArray = makeArray(Size); // create the array
    13.  
    14.   for (int i = 0; i <= Size; i++) { // print out the test
    15.     Serial.println(anArray[i]);
    16.   }
    17.  
    18.   Serial.println();
    19.   halt;
    20.   // normally, array memory should be deleted around here
    21. }
    22.  
    23. // makearray function
    24. char* makeArray(int mySize) { // function returns a pointer
    25.  
    26.   char* myArray = new char[mySize]; // create the array
    27.  
    28.   for (int i = 0; i <= mySize; i++) { // fill the array with test values
    29.     myArray[i] = 65+ i;
    30.   }
    31.   return myArray; // return the pointer to the allocated array
    32. }
    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: Feb 20, 2017
    JohnInTX likes this.
Loading...