By 341008


2010-12-24 00:35:01 8 Comments

I have to define a 24-bit data type.I am using char[3] to represent the type. Can I typedef char[3] to type24? I tried it in a code sample. I put typedef char[3] type24; in my header file. The compiler did not complain about it. But when I defined a function void foo(type24 val) {} in my C file, it did complain. I would like to be able to define functions like type24_to_int32(type24 val) instead of type24_to_int32(char value[3]).

6 comments

@Daniel 2019-09-05 01:13:22

Here's a short example of why typedef array can be confusingly inconsistent. The other answers provide a workaround.

#include <stdio.h>
typedef char type24[3];

int func(type24 a) {
        type24 b;
        printf("sizeof(a) is %zu\n",sizeof(a));
        printf("sizeof(b) is %zu\n",sizeof(b));
        return 0;
}

int main(void) {
        type24 a;
        return func(a);
}

This produces the output

sizeof(a) is 8
sizeof(b) is 3

because type24 as a parameter is a pointer. (In C, arrays are always passed as pointers.) The gcc8 compiler will issue a warning by default, thankfully.

@ysth 2010-12-24 00:44:08

You want

typedef char type24[3];

C type declarations are strange that way. You put the type exactly where the variable name would go if you were declaring a variable of that type.

@Geronimo 2015-03-12 22:04:07

To use the array type properly as a function argument or template parameter, make a struct instead of a typedef, then add an operator[] to the struct so you can keep the array like functionality like so:

typedef struct type24 {
  char& operator[](int i) { return byte[i]; }
  char byte[3];
} type24;

type24 x;
x[2] = 'r';
char c = x[2];

@Michael Morris 2018-12-05 01:04:16

This is a C question, not C++. Neither char& nor operator[] are things that exist in C.

@Gerhard Burger 2014-06-04 11:49:55

From R..'s answer:

However, this is probably a very bad idea, because the resulting type is an array type, but users of it won't see that it's an array type. If used as a function argument, it will be passed by reference, not by value, and the sizeof for it will then be wrong.

Users who don't see that it's an array will most likely write something like this (which fails):

#include <stdio.h>

typedef int twoInts[2];

void print(twoInts *twoIntsPtr);
void intermediate (twoInts twoIntsAppearsByValue);

int main () {
    twoInts a;
    a[0] = 0;
    a[1] = 1;
    print(&a);
    intermediate(a);
    return 0;
}
void intermediate(twoInts b) {
    print(&b);
}

void print(twoInts *c){
    printf("%d\n%d\n", (*c)[0], (*c)[1]);
}

It will compile with the following warnings:

In function ‘intermediate’:
warning: passing argument 1 of ‘print’ from incompatible pointer type [enabled by default]
    print(&b);
     ^
note: expected ‘int (*)[2]’ but argument is of type ‘int **’
    void print(twoInts *twoIntsPtr);
         ^

And produces the following output:

0
1
-453308976
32767

@Steve Jessop 2010-12-24 00:43:54

Arrays can't be passed as function parameters by value in C.

You can put the array in a struct:

typedef struct type24 {
    char byte[3];
} type24;

and then pass that by value, but of course then it's less convenient to use: x.byte[0] instead of x[0].

Your function type24_to_int32(char value[3]) actually passes by pointer, not by value. It's exactly equivalent to type24_to_int32(char *value), and the 3 is ignored.

If you're happy passing by pointer, you could stick with the array and do:

type24_to_int32(const type24 *value);

This will pass a pointer-to-array, not pointer-to-first-element, so you use it as:

(*value)[0]

I'm not sure that's really a gain, since if you accidentally write value[1] then something stupid happens.

@Frerich Raabe 2015-01-12 09:13:35

I think this answer could be improved by mentioning the term decay somewhere (and maybe by pointing out that the situation is worse for returning arrays - which doesn't work at all).

@R.. 2010-12-24 00:44:03

The typedef would be

typedef char type24[3];

However, this is probably a very bad idea, because the resulting type is an array type, but users of it won't see that it's an array type. If used as a function argument, it will be passed by reference, not by value, and the sizeof for it will then be wrong.

A better solution would be

typedef struct type24 { char x[3]; } type24;

You probably also want to be using unsigned char instead of char, since the latter has implementation-defined signedness.

@supercat 2012-09-14 15:51:07

Is there any nice document which describes the corner cases involved with passing typedef'ed arrays as parameters? For example, if a function takes a parameter type24 foo, what would be the sizes, types, and meanings of foo, *foo, **foo, &foo, and &&foo? Have the meanings and legality of any such expressions changed over the years?

@sh1 2013-06-27 16:17:04

Probably worth mentioning the structure packing caveat, as a 24-bit data type might be intended to map to something with differently-defined packing semantics like RGB image data.

@R.. 2013-08-02 14:08:24

@sh1: On all modern real-world ABIs I'm aware of - even ones where misaligned access is very expensive - structures don't get stronger alignment requirements than their members would have without the structure. Of course OP or anyone else using this approach should verify my claim if it's going to matter to their program's behavior and portability.

@phuclv 2014-06-04 12:54:22

Are there any problems when the name type24 duplicates before and after { char x[3]; }?

@R.. 2014-06-04 14:30:48

@LưuVĩnhPhúc: No. The first is the struct tag and the second is the type name you're making with typedef.

@Gerhard Burger 2014-06-04 17:11:52

@supercat I was also curious, so I made up an example where it goes wrong. I posted it below.

@baibo 2014-08-04 16:44:36

@R.. One part of this is misleading - in C, arrays are always passed by reference, i.e., if you modify the array passed as an argument to a function, you do so globally, not only in the context of the function. This being said, one could also argue that in C arrays are always being passed by value since we simply pass the address of the first element, which is copied onto the stack on the callee stack. In both cases, however, the answer is misleading.

@bobbogo 2016-02-18 16:01:05

Sadly for the struct formtation, sizeof(type24) is unlikely to be 3. You'll probably need a few compiler dependent fixes. Fortunately you can ensure those fixes are used with a judicious static_assert.

@R.. 2016-02-18 17:14:45

@bobbogo: Have you checked this? I'm pretty sure it's 3 on all interesting targets.

@bobbogo 2016-02-18 17:20:15

It may be 3 on your targets. Presumably you have structure packing on in your compiler? Not portable though. Cygwin says $ cat 1.cpp: struct three { char three[3]; }; static_assert(sizeof(3) == 3, "urk"); and $ g++ -std=c++11 1.cpp gives 1.cpp:2:1: error: static assertion failed: urk static_assert(sizeof(3) == 3, "urk");

@R.. 2016-02-18 18:20:27

@bobbogo: That's not packing, it's just non-insertion of gratuitous padding. The alignment of the structure is just the maximum alignment of any of its members, all of which have alignment 1.

@R.. 2016-02-18 18:22:24

@bobbogo: Your test is buggy. 3 is an int, and sizeof(int)!=3.

@bobbogo 2016-02-20 19:58:00

@R. Yes you are right! A struct that has only char members will have no padding. I'm so used to the compiler adding padding to align longer types that I've missed this special case. Well, live and lean I suppose. (Oh, I must read my own code—I wouldn't employ me :-).)

Related Questions

Sponsored Content

89 Answered Questions

[SOLVED] How do I remove a particular element from an array in JavaScript?

  • 2011-04-23 22:17:18
  • Walker
  • 6168078 View
  • 7692 Score
  • 89 Answer
  • Tags:   javascript arrays

41 Answered Questions

[SOLVED] Loop through an array in JavaScript

34 Answered Questions

[SOLVED] Create ArrayList from array

47 Answered Questions

[SOLVED] How to check if an object is an array?

47 Answered Questions

33 Answered Questions

[SOLVED] For-each over an array in JavaScript?

10 Answered Questions

[SOLVED] Improve INSERT-per-second performance of SQLite?

16 Answered Questions

[SOLVED] How to insert an item into an array at a specific index (JavaScript)?

13 Answered Questions

[SOLVED] What is a typedef enum in Objective-C?

30 Answered Questions

[SOLVED] How to append something to an array?

Sponsored Content