4

I am working with a source base with a unclear for me rule on pointer types definition: using _PTR_ macro instead of *. So, all the function prototypes and typedefs look like:

extern FILE_PTR    _io_fopen(const char _PTR_, const char _PTR_);

I wonder what could be the rationale behind this since for me this seems excessive.

EDIT

By the way, for double indirection I found:

_io_strtod(char _PTR_, char _PTR_ _PTR_);
pmod
  • 10,450
  • 1
  • 37
  • 50
  • 1
    Good question. I'm really curious to see if anyone has a good answer to this one. Do you see `__PTR__ __PTR__` for double indirection too? :S – Michael Mior Sep 19 '11 at 14:47
  • 3
    lol ... maybe the programmer who came up with that had vision issues and difficulty in recognizing the small asterisks in the middle of all other symbols present in a typical source file. – pmg Sep 19 '11 at 14:48
  • @Michael Mior Ha-ha - there are :) – pmod Sep 19 '11 at 14:51
  • 1
    Ugh. I can't think of a *rational* reason for doing something like that. Do they use the macro for dereferences as well? For example, do they actually write something like `x = _PTR_p`? Do they write declarations like `int (_PTR_x)[N]`, or `char _PTR_(_PTR_foo)(void)`? If not, then I submit the macro is *worthless* and should be factored out. If you can't deal with pointer syntax, don't work in C. – John Bode Sep 19 '11 at 14:52
  • 1
    Looks like something only a quiche-eating Pascal programmer could come up with.. – janneb Sep 19 '11 at 14:55
  • Whatever the reason, don't copy it. Same goes for idiotic things like `#define BEGIN {`. The purpose of the preprocessor is NOT to make C look like whatever other language you're used to... – R.. GitHub STOP HELPING ICE Sep 19 '11 at 17:04
  • @R.. The thing is that some components based on that do follow this rule in order to be consistent. So in our case, consistency outweighs "idiotic things", however at least one point was provided here ... – pmod Sep 19 '11 at 19:08
  • @Michale Mior: You seem to be missing a major part of you programmer education: http://www.pbm.com/~lindahl/real.programmers.html – janneb Sep 19 '11 at 20:05

2 Answers2

6

It is possible that the definition is for compatibility with DOS.

#ifdef DOS
#define _PTR_ far *
#else
#define _PTR_ *
#endif

The far / near keywords allow pointers to address memory inside / outside the current segment, allowing programs to address more than 64 KiB of memory while still keeping the benefits of 16 bit pointers for faster code / less memory usage.

It is more typical to exclude * from the definition. For example, in LibPNG, you can see definitions like:

typedef png_color FAR * png_colorp;
typedef png_color FAR * FAR * png_colorpp;

On most platforms, FAR will be #defined to nothing.

Although DOS is long past, some modern embedded architectures have similar issues. For Harvard architecture processors, pointers to program and data memory must be accessed using different instructions, so they have different types. Other processors have different "data models", and it is not uncommon to see special pointer types for pointers below 2^24, 2^16, or 2^8.

Dietrich Epp
  • 205,541
  • 37
  • 345
  • 415
  • Well, maybe, however what I can see is that it is #define _PTR_ * and in part of code related to platform related specific (code is not for building under DOS, actually this is inside a RTOS). So, probably they wanted to keep code portable for the far (ha=ha) future... – pmod Sep 19 '11 at 15:02
  • @pmod: Many embedded architectures have different kinds of pointers, just like DOS, so that could explain it. – Dietrich Epp Sep 19 '11 at 15:05
  • I don't think this answer makes sense. If you wanted ALL pointers to be far on DOS, you would use the large/huge memory model. If you only want SOME pointers to be far, then calling the macro `_PTR_` does not make sense... – R.. GitHub STOP HELPING ICE Sep 19 '11 at 19:44
  • @R..: This was from LibPNG, which is a library. They may need all the pointers to be far, but they don't want to force application developers to use a different memory model. – Dietrich Epp Sep 19 '11 at 22:54
  • Well the name `FAR` makes sense. Also, unlike `_PTR_`, it's valid, portable C. (`_PTR_`, beginning with an underscore and a capital letter, is in the reserved namespace and thus not valid to use) – R.. GitHub STOP HELPING ICE Sep 19 '11 at 23:19
0

That's a good convention to easily (for sufficiently small definitions of easily) differentiate between multiplication and indirection

int _PTR_ arr = malloc(42 * sizeof _PTR_ arr);
pmg
  • 106,608
  • 13
  • 126
  • 198
  • 2
    Eh, `int * arr` does not look like multiplication ;D – Griwes Sep 19 '11 at 14:54
  • Not there, @Griwes: in the malloc argument! Also `42**arr` == `42*_PTR_ arr` == `42*arr[0]` – pmg Sep 19 '11 at 14:58
  • That's why I always add spaces in proper places... `42 * (*arr)` or `42 * *arr` is clearer and does not involve some unreadable and upper-case (= ugly) macro. And with `sizeof`, just use `42 * sizeof(*arr)`, if you need such expression... – Griwes Sep 19 '11 at 15:00