Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Curious error message

This thread is locked; no one can reply to it. rss feed Print
Curious error message
Andre Xavier
Member #16,694
June 2017

Hellows peeps!

Im studying strings and I stumbled on a lot of functions to read and write and have been trying to make just enough code to read an input and print it to the screen. Nothing big, yes, but Im curious about this error message and what it means.

char *commandLine;
int commandLineRead;
int commandLineSize = COMMANDLINE_SIZE;

commandLine = (char *) malloc(COMMANDLINE_SIZE);

printf("Enter command: ");
getline(&commandLine, &commandLineSize, stdin);
printf("Seu comando: %s", commandLine);

free(commandLine);

Where COMMANDLINE_SIZE = 21.

Then the mean compiler complains saying this:

C:\Users\Xavier\Documents\Programming Projects\Inferno Verde\main.c|81|warning: pointer targets in passing argument 2 of 'getline' differ in signedness [-Wpointer-sign]|

c:\mingw\include\stdio.h|614|note: expected 'size_t * restrict {aka unsigned int * restrict}' but argument is of type 'int *'|

What is this signedness thing?

And could someone point me out some good place on the net to study C more deeply? That would surely help! Ive been seeing some sites around but I noticed that most dont develop the subject really deep enough, like passing multisized matrix as references or as pointers. Some, on the other hand, can be really confusing...

Thanks in advance!

Xavier

=^.^=

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

Read the man page : https://linux.die.net/man/3/getline

It says the second parameter is a size_t *n. That means you need to pass a pointer to an unsigned int to it, because that's what a size_t is. That's why it's complaining about an int* because it's signed.

EDIT

passing multisized matrix as references or as pointers

Tip - stick to single dimensional arrays, even when making "2D" or "3+D" arrays. All you need is a pointer to the beginning of the array, the width, and height of the matrix and the x,y,z coordinate in the array.

Andre Xavier
Member #16,694
June 2017

Hellows, Ed!

Thanks again for the help! I found that page very interesting and made me think about linux, but that will be for the future. :)

Im trying to make an oldschool, very small text game, just like those old games where you just had to read a description and write the commands to see what happens. I thought that would be simple enough to begin with and would be educative to implement, as I will need to relearn everything.

I have many ideas but the main things Im using are a single string for the command line, a 2d matrix to keep the map and Im considering to use a 3d matrix to keep the items that are left at the "rooms". Other than that a structure for the player and another for the scenario, since there will be at least three different areas to explore.

The whole idea seems very simple and once its set I think Ill have just to fill in with more text for this and that items, places and problems to solve. At this point Im focusing in making the basic movement on the rooms work.

Im still open to suggestions about a place to check for learning more C on the net. :D

If I would stick to unidimensional matrixes I would have to use one for the x, another for the y, and so on, right? That dont make everything more confusing to code? Or would take more work to do?

Thanks again and hugs!
Xavier

=^.^=

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

The key is to understand the difference between true 1, 2, and 3D matrices.

If you allocate the entire matrix in one call to malloc it will be contiguous in memory. Otherwise it will be fragmented. You can use a true "3D" array by using pointers to pointers to pointers but it makes everything so complicated.

A.

int size = width*height*depth;
int* array = (int*)malloc(sizeof(int)*size);
for (int i = 0 ; i < size ; ++i) {array[i] = 0;}
array[z*(width*height) + y*height + x] = x + y + z;

(EDIT I don't even know if this will compile) Versus B.

int*** array3d = (int***)malloc(sizeof(int**)*depth);
for (int i = 0 ; i < depth ; ++i) {
   array3d[i] = (int**)malloc(sizeof(int*)*height);
   for (int j = 0 ; j < height ; ++j) {
      array3d[i][j] = (int*)malloc(sizeof(int)*width);
      for (int k = 0 ; k < width ; ++k) {
         array3d[i][j][k] = 0;
      }
   }
}
array3d[z][y][x] = x + y + z;

Now which one of those structures looks easier to free? If you simply use a little math to access your elements its no problem.

One of the best places to learn C and C++ are from the docs :

http://en.cppreference.com/w/

http://www.cplusplus.com/

The second site has a great set of tutorials, good for learning C++.

Andre Xavier
Member #16,694
June 2017

Thanks again, Ed. :D

I anderstand your point. Definitely the first example looks a LOT less complicated and less risky too.

Since you said a pointer to a pointer to another pointer I suppose the 3 * at that type cast (int***) have to do with that? I didnt know this would be possible. So, lets say, 5 pointers in this same sequence would make a type cast of (int*****)?

And why all the pointers instead of just using array[z][y][x] or passing it as reference, since the array is itself a pointer? Or am I saying nonsense?

Definitely it looks more complicated but Im still curious. Ill stick to the first example anyway. Why to complicate when one can keep it simple... :)

Hugs,
Xavier

=^.^=

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

Audric
Member #907
January 2001

a 2d matrix to keep the map and Im considering to use a 3d matrix to keep the items that are left at the "rooms"

The items had rather be stored in a collection which belongs to your room objects (or structs). For example a doubly-linked list, since they allow easy removal of an element, and this is something you'll have to do whenever the player picks something up.

Andre Xavier
Member #16,694
June 2017

Hellows peeps!

At this point I have a game map that is walkable by simple north, south, east and west command lines and some few others. Im focusing in making the basic interaction works before expanding. There will be some more maps once the first is completed.

Im using some structures to keep track of all the data but Im not daring to use a linked list yet. Not sure if Ill know how to do it at this point. Basically Im using predefined sizes for the item arrays and using one array for each room, yes. That made me wonder on how to check how much RAM the game is using while running. I checked with the task manager and it says 0.5M. Can I trust on this info?

I too realized that, besides this being a text only game, this code may very well be the basis for a graphical rpg or adventure game, since the main mechanics of walking around and interaction will be already done, needing just some adjusting to insert the pretty pics or funny sprites. Just a matter of recycling code, it seems. :D

Audric, could you please elaborate more on the use of linked lists that you suggested? It seems very interesting! :)

Another quick question - When I pass a structure as a parameter is it passed a copy of the original structure, just like variables? I just noticed this happening when I pass a structure to a function to change the y coordinate after giving the north command and inside the function y have the new value but outside of it the value kept is the original, pre function one, what made me use a pointer.

I have yet another question:

I create these data structures:

struct mapData
{ int mapArea;
int mapLength; //Length and width for general purpose calculations
int mapWidth;
int mapSize; };

struct roomData
{ int areaType;
int exitN;
int exitS;
int exitE;
int exitW;
struct characterData characterList[10];
struct itemData itemList[10]; };

Then I create the structures and initialize them:

struct mapData mapJungle = { MAP_JUNGLE_AREA, --- //Value 0
MAP_JUNGLE_LENGTH, --- //Value 6
MAP_JUNGLE_WIDTH, --- //Value 10
MAP_JUNGLE_LENGTH * MAP_JUNGLE_WIDTH }, --- //Value 60
mapBuffer = { MAP_BUFFER_AREA,
MAP_BUFFER_LENGTH,
MAP_BUFFER_WIDTH,
MAP_BUFFER_LENGTH * MAP_BUFFER_WIDTH };

struct roomData roomJungle [mapJungle.mapSize] = /*gigantic initializer not worth to print here :D */
And I get this error:

error: variable-sized object may not be initialized //Points to the roomJungle line
warning: excess elements in array initializer //Points to the line just below

But if I change it to

struct roomData roomJungle [60] = /*gigantic initializer not worth to print here :D */

or

struct roomData roomJungle [MAP_JUNGLE_LENGTH * MAP_JUNGLE_WIDTH] = /*gigantic initializer not worth to print here :D */

There are no errors... But both have the same value (60). What am I missing here? ???

Thanks all for the support!

Hugs,
Xavier

=^.^=

Audric
Member #907
January 2001

In the C language, arrays have fixed size, known at compile time. There is a kind of dynamic array with [], but you may want to practice with pointers and dynamic allocation (malloc()) before using it.

C-style linked list is when an instance of a struct acts as an chain link : Every instance contains a pointer to the next instance of the chain. The last one's pointer will point to NULL, to mark the end. This leads to such code, very common in C:

// Perform an action on all items of "room"
itemData *obj = room->items;
while (item != NULL) // This condition is never entered if the room has no item at all (items == NULL), otherwise it will stop after handling the last item : the one whose ->next_item pointer is NULL
{
   doAction(item);
   item = item->next_item;
}

// Same code, as a single 'for' loop :
for (itemData *item = room->items; obj != NULL; item = item->next_item;
   doAction(item);

At this point I suggest you find a readable tutorial on linked lists. There are more complex structures and variants (which makes it easier and faster to count elements, add/remove, etc), but skipping the basics may cause you to waste a lot of time. Don't hesitate to make diagrams on paper, with arrows to represent "This pointer contains the address of ...".

Go to: