CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 14 of 14
  1. #1
    Join Date
    May 2009
    Location
    Boston
    Posts
    364

    question about some declarations in c

    Hello,

    I am reading some c code that I didn't write and I am unclear about how some declarations are working. For the following statements,

    Code:
    int *group;
    group = (int *) malloc(sizeof(int *) * t->input_info.count); // input_info.count is an int 
    group[0] = t->input_count; // input_count is an int
    ...
    group is used for some things
    ...
    free(group);
    This appears to declare group as a pointer to an integer. The pointer group is then initialized to to point to dynamically-allocated memory sized for a specific number of ints. Next, group is accessed as an array and an int is assigned to the first element.

    This makes no sense to me.

    Would group not have to be declared as an array of int to access an element?

    Does initializing the pointer to point to a block of memory larger than a single int tell the compiler that this is an array?

    I guess there are issues in dynamically declaring an array size, so perhaps this is how you get that behavior in c. I generally program in c++ and would use a container for this so I don't know.

    I don't know much about automatic variables in c so I would appreciate some insight here.

    LMHmedchem
    Last edited by LMHmedchem; April 7th, 2018 at 11:53 AM.

  2. #2
    2kaud's Avatar
    2kaud is online now Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,824

    Re: question about some declarations in c

    This appears to declare a pointer to an integer. Then the pointer is initialized to to point to dynamically-allocated memory that is sized for a specific number of ints. Then, group is accessed as an array and an int is assigned to the first element.
    Correct.

    Would group not have to be declared as an array for this to work?
    No. A pointer to a block of memory can be accessed just like accessing an array. All an array really is is a block of contiguous memory.

    Does initializing the pointer to point to a block of memory larger than a single int tell the compiler that this is an array?
    No. Any pointer to memory can be accessed as if it is an array. If you allocate memory for a single int and then access the fifth element, the compiler will do just that for you. This is out of bounds memory access and is a major source of issues. Note that the same issue arises even with a declared array. You can access an array element outside of its bounds - with unknown results! When arrays are passed as parameters to functions, they are effectively passed as a pointer. That's why when passing a one-dimensional array you can specify the function definition as int a[] or int *a. They both mean the same. [] is degraded to a pointer reference.

    PS
    Code:
    group = (int *) malloc(sizeof(int *) * t->input_info.count); // input_info.count is an int
    This should be
    Code:
    group = (int *) malloc(sizeof(int) * t->input_info.count); // input_info.count is an int
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  3. #3
    Join Date
    May 2009
    Location
    Boston
    Posts
    364

    Re: question about some declarations in c

    Thanks for the explanation. Is this how arrays are usually allocated in c in cases where the array size is not known at compile time and dynamic allocation is necessary?

    I am assuming that something like,
    Code:
    int array_size = t->input_info.count;
    int group[array_size];
    is not allowed in c.

    Quote Originally Posted by 2kaud View Post
    Code:
    group = (int *) malloc(sizeof(int *) * t->input_info.count); // input_info.count is an int
    This should be
    Code:
    group = (int *) malloc(sizeof(int) * t->input_info.count); // input_info.count is an int
    My recollection is that a pointer is an int holding a starting memory address so sizeof(int) and sizeof(int *), or any other pointer, would return the same size. Is that correct?

    I guess that would be why the code does not fail. I know that this code works, but I don't know as of yet how well formed it is.

    I did a search and found a number of other instances where malloc() was called using, for example, sizeof(char *).

    Code:
    lowers = (char **) malloc(sizeof(char *) * count);
    This would appear to be allocating space for a character array the size of count. Is the use of sizeof(char *) incorrect as well?

    LMHmedchem

  4. #4
    Join Date
    Jan 2006
    Location
    Singapore
    Posts
    6,765

    Re: question about some declarations in c

    Quote Originally Posted by LMHmedchem
    Is this how arrays are usually allocated in c in cases where the array size is not known at compile time and dynamic allocation is necessary?
    Yes, though it may be done through other (non-standard with respect to the C standard) library functions, but with essentially the same idea.

    Quote Originally Posted by LMHmedchem
    I am assuming that something like,
    Code:
    int array_size = t->input_info.count;
    int group[array_size];
    is not allowed in c.
    It is allowed in C99, or in C11 if the compiler supports the optional use of variable length arrays and it is thus enabled, and may be supported pre-C99 if your compiler allows for a variable length array extension.

    Quote Originally Posted by LMHmedchem
    My recollection is that a pointer is an int holding a starting memory address so sizeof(int) and sizeof(int *), or any other pointer, would return the same size. Is that correct?
    No, that is not correct, e.g., sizeof(int*) might be equal to sizeof(long) or sizeof(long long), i.e., you have no such guarantee and so you should not depend on that.

    Quote Originally Posted by LMHmedchem
    This would appear to be allocating space for a character array the size of count. Is the use of sizeof(char *) incorrect as well?
    Without knowing the type of lowers, it is futile to try and answer that question, though it looks like the intent is to allocate count number of pointers to char, not "space for a character array the size of count", but perhaps lowers is actually a char* and so you're right and the code is wrong, but who knows? However, if lowers is a pointer and the aim is to allocate count number of what lowers points to, then this is correct regardless of the exact type of lowers:
    Code:
    lowers = malloc(sizeof(lowers[0]) * count);
    Of course, you need to cast the return value of malloc if this were C++ instead.
    C + C++ Compiler: MinGW port of GCC
    Build + Version Control System: SCons + Bazaar

    Look up a C/C++ Reference and learn How To Ask Questions The Smart Way
    Kindly rate my posts if you found them useful

  5. #5
    2kaud's Avatar
    2kaud is online now Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,824

    Re: question about some declarations in c

    Code:
    lowers = (char **) malloc(sizeof(char *) * count);
    As laserlight says in post #4, whether this is right or wrong depends upon what is trying to be achieved. lowers seems to be a pointer to a pointer of char (char**). malloc is allocating memory to hold these pointers (of type char*) so in this case sizeof(char*) is right if that is what is wanted. Consider

    Code:
    char ** lowers;
    int count = 3;
    lowers = (char **) malloc(sizeof(char *) * count);
    char * s1 = "qwewt";
    char * s2 = "!asdf";
    char * s3 = "zxcv";
    lowers[0] = s1;
    lowers[1] = s2;
    lowers[2] = s3;
    In general, the 'number of * used in the sizeof in malloc/calloc etc is one less than that used in the cast on the return value'

    It is allowed in C99
    but not in standard c++ (any version) - but I understand that some c++ compilers have an extension that allows this(?).
    Last edited by 2kaud; April 8th, 2018 at 05:42 AM.
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  6. #6
    2kaud's Avatar
    2kaud is online now Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,824

    Re: question about some declarations in c

    a pointer is an int holding a starting memory address so sizeof(int) and sizeof(int *), or any other pointer, would return the same size
    Further to laserlight's reply in post #4. Back in the 1990's 'most' computer systems were 32 bits. So the size of a pointer (to anything) was 32 bits (4 bytes). Also the size of an int was 32 bits. short int was typically 16 bits and long int was often the same as an int as 32 bits. This meant that the size of a pointer (to anything) and the size of an int/long int was the same. Hence an int could hold a memory address and sizeof(int) and sizeof(t*) [where t is any type] would return the same value. Hence much code written back then incorrectly often exchanged int/int* in code which on 32 bit systems with 32 bit ints worked correctly but was ill-formed code. Much of that code still exists today. However, when you start compiling for 64 bit systems, the size of a pointer is now 64 bits and on some c systems int is still 32 and on others int is now 64 bits (note that the standard doesn't specify the size of the basic types - only a guarantee regarding relative sizes). So you'll now get code that 'worked' for 32 bits but doesn't necessarily work for 64 bits.

    Also consider

    Code:
    int sz = 2;
    char * pch = (char*)malloc(sizeof(char*) * sz);
    Assuming that the size of a char is 8 bits (1 byte) and on a 64 bit complier then sizeof(char*) is 8 bytes so 16 bytes is being allocated where only 2 bytes are actually needed to be allocated. In this case the program works but is wasteful of memory. However consider

    Code:
    int sz = 2;
    int pt = (int)malloc(sizeof(int) * sz);
    This type of code used to be common. However for a 64 bit compiler malloc would allocate 8 bytes with possibly a memory address greater than the range which can correctly be represented by an int (assuming int is 32 bits). The compiler won't complain as a cast is used so it assumes the programmer knows what they're doing. In this case the program may well work some of the time (possibly during testing when memory usage is light) and fail at other times (on the customers machine when memory usage is heavy) - often apparently completely at random!

    For c/c++ (but especially c), just because a program 'seems' to work, doesn't mean it is correct and not ill-formed! Issues with memory in c was one of the driving factors behind much of the work in c++ re managed pointers and having new rather than malloc etc.
    Last edited by 2kaud; April 8th, 2018 at 05:34 AM.
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  7. #7
    Join Date
    May 2009
    Location
    Boston
    Posts
    364

    Re: question about some declarations in c

    Quote Originally Posted by 2kaud View Post
    For c/c++ (but especially c), just because a program 'seems' to work, doesn't mean it is correct and not ill-formed! Issues with memory in c was one of the driving factors behind much of the work in c++ re managed pointers and having new rather than malloc etc.
    I am in the process of going through the code to evaluate this kind of thing. The code is fairly new, so I would be surprised if I don't find anything more.

    I need to store some data that is currently being written to a file. I will be storing the data instead and processing it in memory before writing output. In c++, I would use a container of objects to store the data because I don't know at compile time how many units of data I will be generating or how much data will be in each unit. I was thinking of adding some c++ functions to the existing c code, but would it make more sense to stick with c?

    It looks like I could do something analogous to say, a vector of objects, with a struct and malloc like the example here. If I were to do the following as a simple example,

    Code:
    // structure to hold each data unit
    typedef struct {
       // index number
       int e_number;
       // value for each row
       float *row_value;  // will be dynamically sized to be addressed like an array
       // group value for each row
       char *row_group;  // will be dynamically sized to be addressed like an array
    } e_data;
    
    // number of data units, would normally be calculated at runtime
    int list_size = 1500;
    
    // number of processed rows, would normally be calculated at runtime
    int num_rows = 2000;
    
    // "array of objects"...ish to hold data objects
    e_data *data_list;
    
     // size list so that list_size number of e_data objects can be addressed
    data_list = (epoch_data *) malloc(sizeof(epoch_data) * list_size);
    
    // possibly add objects to data_list here
    
    // loop iterator
    int i = 0;
    
    // size object member arrays
    for(i=0; i<list_size-1; i++) {
       // size array of float in each object to number of rows
       data_list[i].row_value = (float *) malloc(sizeof(float) * num_rows);
       // size array of char in each object to number of rows
       data_list[i].row_group = (char *) malloc(sizeof(char) * num_rows);
    }
    Would something like this work to store and access a number of objects? This is just a guess, so I am sure that the above is far from working syntax but would something along these lines be a reasonable solution or am I better off writing some c++ code and getting it to talk to the existing c code?

    LMHmedchem
    Last edited by LMHmedchem; April 8th, 2018 at 10:12 PM.

  8. #8
    2kaud's Avatar
    2kaud is online now Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,824

    Re: question about some declarations in c

    Yes - apart from

    Code:
    data_list = (e_data *) malloc(sizeof(e_data) * list_size);
    data_list can then be accessed as an array and its members row_value and row_group can be accessed as arrays. Depending upon the size, will all the data fit into memory as you mention that it is currently written to file?

    The allocated memory will need to be free'd at some point when not required.

    a reasonable solution or am I better off writing some c++ code and getting it to talk to the existing c code
    This is really a question of judgement and what is involved (time to do etc) in the two scenarios (and which you feel the most comfortable with). If you add some c++ functions to existing c code then the whole code has to become c++ (which might not be a bad thing and converting from c to c++ can be fairly easy or hard depending upon the code) - or you add a c++ file to the solution and have a solution of mixed c and c++ files. In this case the interface between them (functions?) needs to be c. If the conversion to c++ seems to be too involved or the required processing isn't that much more easier in c++ than c, then I would be inclined to stick with c. There's nothing wrong with c if coded properly.
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  9. #9
    Join Date
    May 2009
    Location
    Boston
    Posts
    364

    Re: question about some declarations in c

    Quote Originally Posted by 2kaud View Post
    If you add some c++ functions to existing c code then the whole code has to become c++ (which might not be a bad thing and converting from c to c++ can be fairly easy or hard depending upon the code) - or you add a c++ file to the solution and have a solution of mixed c and c++ files. In this case the interface between them (functions?) needs to be c.
    My biggest issue with c is that I don't know it very well.

    I have a fair amount of code that is a mixture of c, c++, and g77, so I am more or less familiar with the syntax for communicating between functions and how the make file needs to be set up. The main issue with calling a c++ function from c for storage purposes is that the data being stored usually needs to be stored on the c++ side since you were calling c++in the first place to use containers and such. I haven't figured any way to do that other than using a container declared as a global variable in a c++ src file. Otherwise, you lose all the objects you populated when the c++ function returns. I am not as opposed to using global variables as some are, but I do try to avoid them unless I can't think of anything else. You could stick to c style structs, but if you know how to make that work for what you need, you might as well just stick with c.

    Another option is to run the application from some kind of c++ wrapper that calls the c code as a function. Then the c++ wrapper code can do what it likes with the data returned from the c function. This means creating a new front end in c++ which may mean wading in deeper than you want.

    I have never converted a large c application to c++, so I don't know how that would go. The issue is always code that looks like it is working but giving unexpected behavior under the hood.

    LMHmedchem

  10. #10
    2kaud's Avatar
    2kaud is online now Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,824

    Re: question about some declarations in c

    IMO I would suggest the way forward is with what you feel most comfortable. Converting a c program to c++ could be as simple as changing the file extension! Much of c is a subset of c++ (with a few exceptions). So the code in post #7 for example would be valid c++. If you can get the c code to compile as c++ then you can use the c++ containers etc for new code and keep the existing code as is. The issue here is how many errors are produced by the c++ compiler and how easy they are to fix. I've done this with some c programs that generated hundreds of compiler errors, but most were of the same type (type conversions if I remember) and a few global find/replaces fixed the majority. The remaining few were fixed one at a time. If I remember right it took me about a couple of hours to get a large c program to compile cleanly as c++ (using Visual Studio).
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  11. #11
    Join Date
    May 2009
    Location
    Boston
    Posts
    364

    Re: question about some declarations in c

    I guess I will try to compile this in c++ and see what happens. I would change the file extensions and then add a compile rule for %.cpp. If there are not too many issues and I can confirm that the compiled code produces the same results, then it will be easier to add the functionality that I need. Otherwise, I will have to look at adding some c++ in separate src files so they can be compiled as separate objects.

    Would there be any difference in the included header files? This doesn't use much of anything out of the ordinary,

    Code:
    <stdio.h>
    <string.h>
    <stdlib.h>
    <pthread.h>
    <errno.h>
    <sys/types.h>
    <sys/stat.h>
    <math.h>
    but in general my c++ includes don't have the .h extension.

    LMHmedchem
    Last edited by LMHmedchem; April 9th, 2018 at 08:11 PM.

  12. #12
    2kaud's Avatar
    2kaud is online now Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,824

    Re: question about some declarations in c

    c header files (.h) can be used in c++. For c++, the main difference between say stdlib.h (c version) and cstdlib (c++ version) is that the functions within cstdlib are in the std namespace whereas the functions in stdlib.h are in the default namespace. Some c header files don't have an equivalent. The 'rule of thumb' is to add a c at the front and remove the .h. If this file is found then there is a c++ std namespace version available. Also note that the c++ versions include the .h file version. As you are compiling c code as c++, I would suggest initially keeping the .h headers - at least until you're got a clean compile. Then change them to the c++ versions (if available) and add using namespace std. My advice when converting from c to c++ is to initially change as little as possible to get a successful compile. Once that has been achieved then things can be changed as needed.

    Good luck!

    PS As you say you don't know c very well and the c code uses dynamic memory, look out for the following which can catch people out

    Code:
    int *a[10];
    int (*b)[10];
    They look very similar but have different meanings.

    a is an array of 10 elements of type pointer to int

    b is a pointer to an array of 10 elements of type int
    Last edited by 2kaud; April 10th, 2018 at 05:34 AM. Reason: PS
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  13. #13
    Join Date
    May 2009
    Location
    Boston
    Posts
    364

    Re: question about some declarations in c

    Quote Originally Posted by 2kaud View Post
    Code:
    int *a[10];
    int (*b)[10];
    They look very similar but have different meanings.
    a is an array of 10 elements of type pointer to int
    b is a pointer to an array of 10 elements of type int
    So,
    Code:
    int (*b)[10];
    is sort of the equivalent of,
    Code:
    int a[10];
    int *b = &a;
    except the syntax is more compact and in the first case there has been no declared way to address the array other than using the pointer?

    LMHmedchem

  14. #14
    2kaud's Avatar
    2kaud is online now Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,824

    Re: question about some declarations in c

    Code:
    int a[10];
    int *b = &a;
    is sort of the equivalent of
    No. b is a pointer to an int, but a is an array of 10 elements so the address of a can't be assigned to b as the types are different. You can do

    Code:
    int a[10];
    int (*b)[10] = &a;
    and

    Code:
    int a[10];
    int *b = &a[2];
    as here b is a pointer to an int which is assigned the address of the 3rd element of the array b.
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured