Author Topic: how do you identify what are the preprocessor and macros in c program  (Read 8659 times)

0 Members and 8 Guests are viewing this topic.

Online brucehoult

  • Super Contributor
  • ***
  • Posts: 4207
  • Country: nz
Let's say it simple and concise:
don't use macro. Never.

edit: bold

Disagree.

I am 100% convinced that the preprocessor is THE reason that hacky ugly C won out over functionally-equivalent but more "pure" languages such as Pascal.

The preprocessor, skilfully used, enables extreme portability of code between very different systems, while keeping the main body of the code compact and readable.

As an example of proven extreme portability over 30+ years and dozens of different systems, I present the Boehm GC:

https://github.com/ivmai/bdwgc/blob/master/include/private/gcconfig.h
 

Offline SiliconWizard

  • Super Contributor
  • ***
  • Posts: 14869
  • Country: fr
The preprocessor, skilfully used, enables extreme portability of code between very different systems, while keeping the main body of the code compact and readable.

I agree with that. And not just for portability. It simply allows to avoid code duplication and makes modifications easier - that goes beyond portability.

Sure it's simple and raw. With potential pitfalls. But very flexible. Most attempts at replacing it with a "cleaner" approach for metaprogramming (such as C++ templates, or various kinds of so-called "hygienic" marcro systems) have usually led to monsters to just be able to compete with the flexibility. Sure they are safer, more elegant ... etc... but to allow the same amount of flexibility, they inevitably need to grow to untractable monsters. And with C++, you still see some amount of preprocessor being used.

While the simplicity of the C preprocessor (like the simplicity of C) can be "dangerous", it's also a benefit. As long as you know how it works (and it IS simple), looking at a macro definition (unless it's absolutely horrible, like obfuscated C contest-worthy) will tell you how it expands rather easily. The same is not necessarily true for complex template stuff.

Sure there ARE horrific uses ot the preprocessor (as well as horrific uses of any language), but that doesn't mean it's bad or should be avoided at all costs.

As to Pascal, I think it was missing a bit too much - at least in its original form - to be really usable for anything either moderately complex (it didn't have separate compilation or modules!), or moderately low-level. Not just a matter of preprocessor here. So in the early 70's, not sure Pascal would have been able to "compete" even if it got a preprocessor.
Later variants of Pascal got a lot more features, so that's a different story. But it was too late.
 
The following users thanked this post: Siwastaja, Ian.M, newbrain

Online brucehoult

  • Super Contributor
  • ***
  • Posts: 4207
  • Country: nz
As to Pascal, I think it was missing a bit too much - at least in its original form - to be really usable for anything either moderately complex (it didn't have separate compilation or modules!), or moderately low-level. Not just a matter of preprocessor here. So in the early 70's, not sure Pascal would have been able to "compete" even if it got a preprocessor.
Later variants of Pascal got a lot more features, so that's a different story. But it was too late.

Sure, the very first version was too limited. But it quickly got extended and by 1977 or 1978 things such as UCSD Pascal and VAX Pascal were completely suitable for both systems and application programming. Apple Lisa and then Mac were programmed in Pascal (including all of the OS that wasn't in assembly language). I believe the same goes for early Windows.

I don't think C was at all available or popular outside of Unix until 1985 or 1986. I never used plain C at all in those days -- I went straight from (Object) Pascal to C++ in 1989/90.
 

Offline SiliconWizard

  • Super Contributor
  • ***
  • Posts: 14869
  • Country: fr
And there was Turbo Pascal. Which did a lot to make Pascal popular for a while.

I don't know about very early Windows, but the Windows API that I've run into (from Windows 3.1 to... current) has always exposed C interfaces. But I seem to remember that the calling convention of a lot of the API was actually Pascal - so that may come from the early days, and you may be right.

As I remember, for "general-purpose use", C started to be talked about in the late 80's indeed. I remember computer magazine articles, from that period (maybe 87, 88) that talked about C as the language you should start taking a look at...

C was still popular as a language on Windows until mid to late 90's. Remember the famous Petzold's books.

But from say mid 90's to today, I think the *popularity* of C has been mostly due to Linux on one hand, and embedded dev on the other hand.
 

Offline Ian.M

  • Super Contributor
  • ***
  • Posts: 12955
I had Hitech Hisoft C on my ZX Spectrum back in 1984.  IIRC it didn't play well with the ZX Microdrives (Sinclair's attempt at random access storage using an endless tape loop in a cartridge somewhat similar to an eight track cassette but smaller than a thin matchbox).  Then I bought a 68000 C compiler for my Sinclair QL in '87, and disk drives as well because compiling from Microdrive was painfully slow and somewhat unreliable, and for part of 1990 I was employed writing a graphical scientific application in Microsoft C 6.0 to run under DOS and Windows 2.0.  I don't think I was a particularly early adopter as I know a number of universities were teaching engineers C programming by the mid '80s.
« Last Edit: March 05, 2022, 07:57:40 am by Ian.M »
 

Online brucehoult

  • Super Contributor
  • ***
  • Posts: 4207
  • Country: nz
I had Hitech C on my ZX Spectrum back in 1984.

That would have been on CP/M?

I didn't have much experience of CP/M except for a DEC Rainbow in 1984 (which only had Turbo Pascal that I recall), then the CPC664 a couple of years later. But it was pretty familiar as I'd previously used DEC's RT/11.

Oh! I also did a little consulting job helping some engineer get a printer working on a Kaypro. That would I think have been summer 83-84. So my first experience of CP/M.
 

Offline Ian.M

  • Super Contributor
  • ***
  • Posts: 12955
Sorry about the brain-fart.  I had Hisoft C on the ZX Spectrum, which compiled from cassette tape or a RAM buffer.  As the ZX Spectrum didn't have a cassette control interface, compilation from tape involved a lot of noting of tape counter numbers, rewinding, and start/stopping the tape as directed!  I later got the +3 version which had disc support.  My uncle was the CP/M wizard in the family, and ran a maxed out Amstrad PCW, and in the end, a hard drive on it before he moved onto PCs.
« Last Edit: March 05, 2022, 11:28:08 am by Ian.M »
 

Offline Siwastaja

  • Super Contributor
  • ***
  • Posts: 8291
  • Country: fi
DiTBho: no need to shout.

As for the advice itself: you don’t have any choice. Not unless you want to stop using any library, including the C standard library.

... or build a massive NIH cathedral with new C standard library, complete tooling, even compilers written from scratch or modified ("hacked"), then make this a company policy, so that maybe 5-10 people on the Earth follow this new C-like language, which doesn't even allow * and & for pointer syntax but replaces it with something else. Then start filling threads giving others advice based on this internal paradigm, 98% of the time completely "forgetting" to mention this has nothing to do with normal C, causing massive confusion to everyone.

In other words, I applaud complex and interesting custom solutions; complete descriptions thereof even more; but I hate games like this.
« Last Edit: March 05, 2022, 11:17:02 am by Siwastaja »
 
The following users thanked this post: Ian.M, newbrain

Offline grumpydoc

  • Super Contributor
  • ***
  • Posts: 2906
  • Country: gb
I have to say that I largely agree with SiliconWizard's analysis. C was popular because it was simply easy to write code in, at almost any level of the system from almost bare metal to complex end user systems and everything between.

It was also found on everything from 8-bit CPUs to mainframes.

It helped that it was a simple, but elegant language, easy to learn and even master but with distinct "depth" when needed.

Obviously it was not perfect, quite a few features were essentially missing from the language and had to be handled by system libraries and it is safe to say that it bequeathed to the software industry whole new classes of coding errors.

But it remains my favourite language.

C++ in particular has become too complex - indeed had become too complex around the time I left the software industry in the early 2000's and has only got worse.
 

Online DiTBho

  • Super Contributor
  • ***
  • Posts: 4013
  • Country: gb
Disagree.
I am 100% convinced that the preprocessor is THE reason that hacky ugly C won out over functionally-equivalent but more "pure" languages such as Pascal.

Your opinion, bus sorry, I don't agree with that.

For me, C flexibility with "data-struct" and "data-union" coupled with more powerful "pointer arithmetic"   is one of *THE* reason whey C is better than Pascal in this specific cases, as well as Pascal, Modula2 and Oberon are better about making a project modular. With C ... it's rather impossible.

--

Anyway, I'm more interested in being able to debug and test the code, therefore macro represent a serious problem (especially for team-projects) because
1) specifically because macro have no body and no type (and no namespace)
2) so (especially on the ICE side) the can be easily misused
3) and - worse still - sometimes they expand into very complex code
4) that can be difficult to identify and understand in the preprocessed file
5) also it is easy to make error-prone code in macros
6) and it's impossible to step-in a function-like macro because it's not a true-function
7) so it's impossible to make automated test-cases and automated coverage

In short, I don't like Macro because I cannot debug them, while for sure they can mess up your day, and even if you take the time to fix it, well rationally it's unacceptable that I need to manually care manual testing points with an high probability of being error-prone points instead of safely invoking automating testing tools.
The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 

Online DiTBho

  • Super Contributor
  • ***
  • Posts: 4013
  • Country: gb
but that doesn't mean it's bad or should be avoided at all costs.

DO178C says they must be avoided at all costs until you have a test-case-plan to test your code. Which implies ***you*** have to write manual testing points since you cannot debug Macro.

What makes me annoyed here is that Macro are like public toilets: everybody wants to use them but nobody wants to clean.
« Last Edit: March 05, 2022, 08:03:08 pm by DiTBho »
The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 

Online DiTBho

  • Super Contributor
  • ***
  • Posts: 4013
  • Country: gb
DiTBho: no need to shout.

As for the advice itself: you don’t have any choice. Not unless you want to stop using any library, including the C standard library.

... or build a massive NIH cathedral with new C standard library, complete tooling, even compilers written from scratch or modified ("hacked"), then make this a company policy, so that maybe 5-10 people on the Earth follow this new C-like language, which doesn't even allow * and & for pointer syntax but replaces it with something else. Then start filling threads giving others advice based on this internal paradigm, 98% of the time completely "forgetting" to mention this has nothing to do with normal C, causing massive confusion to everyone.

In other words, I applaud complex and interesting custom solutions; complete descriptions thereof even more; but I hate games like this.

This must be referred to my comments on my builder, which was completely unrelated to the Clang bug because those lines of C show the same defect even with standard C89/C99.

Ok, I made the mistake to quickly test them with what I had on my hands, but why are you still here reproach me it was somehow confusing? and can't I express what I honestly think from 25 years of professional programming experience?

I won't make the same mistake in the future. I promise.
« Last Edit: March 05, 2022, 06:17:28 pm by DiTBho »
The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 

Offline Dadu@Topic starter

  • Contributor
  • Posts: 34
  • Country: in
both gcc and clang have the -E option.


I am using windows 10 operating system.


I'm so sorry.

Quote
What is command for winows


If you use gcc or clang, then the same as anywhere else.

I don't know if there are versions of gcc and clang that work in the DOS command line -- probably -- but you can certainly use them if you install WSL or cygwin.

I believe Mingw-w64 is a port of gcc that can create Windows applications. I'm not sure whether it runs under DOS or in cygwin etc.


one text file generates after running command.  gcc -E hello.c > hello.txt

Code: [Select]
  #include<stdio.h>
#define add(y) ((y) + 1)


int main ()
{
int y = 5;


printf("y = %d ", add(y));

return 0;
}

text file

Quote
# 1 "hello.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "hello.c"
# 1 "c:\\mingw\\include\\stdio.h" 1 3
# 38 "c:\\mingw\\include\\stdio.h" 3
       
# 39 "c:\\mingw\\include\\stdio.h" 3
# 56 "c:\\mingw\\include\\stdio.h" 3
# 1 "c:\\mingw\\include\\_mingw.h" 1 3
# 55 "c:\\mingw\\include\\_mingw.h" 3
       
# 56 "c:\\mingw\\include\\_mingw.h" 3
# 66 "c:\\mingw\\include\\_mingw.h" 3
# 1 "c:\\mingw\\include\\msvcrtver.h" 1 3
# 35 "c:\\mingw\\include\\msvcrtver.h" 3
       
# 36 "c:\\mingw\\include\\msvcrtver.h" 3
# 67 "c:\\mingw\\include\\_mingw.h" 2 3






# 1 "c:\\mingw\\include\\w32api.h" 1 3
# 35 "c:\\mingw\\include\\w32api.h" 3
       
# 36 "c:\\mingw\\include\\w32api.h" 3
# 59 "c:\\mingw\\include\\w32api.h" 3
# 1 "c:\\mingw\\include\\sdkddkver.h" 1 3
# 35 "c:\\mingw\\include\\sdkddkver.h" 3
       
# 36 "c:\\mingw\\include\\sdkddkver.h" 3
# 60 "c:\\mingw\\include\\w32api.h" 2 3
# 74 "c:\\mingw\\include\\_mingw.h" 2 3
# 57 "c:\\mingw\\include\\stdio.h" 2 3
# 69 "c:\\mingw\\include\\stdio.h" 3
# 1 "c:\\mingw\\lib\\gcc\\mingw32\\6.3.0\\include\\stddef.h" 1 3 4
# 216 "c:\\mingw\\lib\\gcc\\mingw32\\6.3.0\\include\\stddef.h" 3 4

# 216 "c:\\mingw\\lib\\gcc\\mingw32\\6.3.0\\include\\stddef.h" 3 4
typedef unsigned int size_t;
# 328 "c:\\mingw\\lib\\gcc\\mingw32\\6.3.0\\include\\stddef.h" 3 4
typedef short unsigned int wchar_t;
# 357 "c:\\mingw\\lib\\gcc\\mingw32\\6.3.0\\include\\stddef.h" 3 4
typedef short unsigned int wint_t;
# 70 "c:\\mingw\\include\\stdio.h" 2 3
# 94 "c:\\mingw\\include\\stdio.h" 3
# 1 "c:\\mingw\\include\\sys/types.h" 1 3
# 34 "c:\\mingw\\include\\sys/types.h" 3
       
# 35 "c:\\mingw\\include\\sys/types.h" 3
# 62 "c:\\mingw\\include\\sys/types.h" 3
  typedef long __off32_t;




  typedef __off32_t _off_t;







  typedef _off_t off_t;
# 91 "c:\\mingw\\include\\sys/types.h" 3
  typedef long long __off64_t;






  typedef __off64_t off64_t;
# 115 "c:\\mingw\\include\\sys/types.h" 3
  typedef int _ssize_t;







  typedef _ssize_t ssize_t;
# 95 "c:\\mingw\\include\\stdio.h" 2 3







# 1 "c:\\mingw\\lib\\gcc\\mingw32\\6.3.0\\include\\stdarg.h" 1 3 4
# 40 "c:\\mingw\\lib\\gcc\\mingw32\\6.3.0\\include\\stdarg.h" 3 4
typedef __builtin_va_list __gnuc_va_list;
# 103 "c:\\mingw\\include\\stdio.h" 2 3
# 210 "c:\\mingw\\include\\stdio.h" 3
typedef struct _iobuf
{
  char *_ptr;
  int _cnt;
  char *_base;
  int _flag;
  int _file;
  int _charbuf;
  int _bufsiz;
  char *_tmpfname;
} FILE;
# 239 "c:\\mingw\\include\\stdio.h" 3
extern __attribute__((__dllimport__)) FILE _iob[];
# 252 "c:\\mingw\\include\\stdio.h" 3








 __attribute__((__cdecl__)) __attribute__((__nothrow__)) FILE * fopen (const char *, const char *);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) FILE * freopen (const char *, const char *, FILE *);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int fflush (FILE *);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int fclose (FILE *);






 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int remove (const char *);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int rename (const char *, const char *);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) FILE * tmpfile (void);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) char * tmpnam (char *);


 __attribute__((__cdecl__)) __attribute__((__nothrow__)) char *_tempnam (const char *, const char *);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int _rmtmp (void);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int _unlink (const char *);
# 289 "c:\\mingw\\include\\stdio.h" 3
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) char * tempnam (const char *, const char *);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int rmtmp (void);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int unlink (const char *);



 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int setvbuf (FILE *, char *, int, size_t);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) void setbuf (FILE *, char *);
# 342 "c:\\mingw\\include\\stdio.h" 3
extern int __attribute__((__cdecl__)) __attribute__((__nothrow__)) __attribute__((__format__(__mingw_printf__,2,3))) __mingw_fprintf(FILE*, const char*, ...);
extern int __attribute__((__cdecl__)) __attribute__((__nothrow__)) __attribute__((__format__(__mingw_printf__,1,2))) __mingw_printf(const char*, ...);
extern int __attribute__((__cdecl__)) __attribute__((__nothrow__)) __attribute__((__format__(__mingw_printf__,2,3))) __mingw_sprintf(char*, const char*, ...);
extern int __attribute__((__cdecl__)) __attribute__((__nothrow__)) __attribute__((__format__(__mingw_printf__,3,4))) __mingw_snprintf(char*, size_t, const char*, ...);
extern int __attribute__((__cdecl__)) __attribute__((__nothrow__)) __attribute__((__format__(__mingw_printf__,2,0))) __mingw_vfprintf(FILE*, const char*, __builtin_va_list);
extern int __attribute__((__cdecl__)) __attribute__((__nothrow__)) __attribute__((__format__(__mingw_printf__,1,0))) __mingw_vprintf(const char*, __builtin_va_list);
extern int __attribute__((__cdecl__)) __attribute__((__nothrow__)) __attribute__((__format__(__mingw_printf__,2,0))) __mingw_vsprintf(char*, const char*, __builtin_va_list);
extern int __attribute__((__cdecl__)) __attribute__((__nothrow__)) __attribute__((__format__(__mingw_printf__,3,0))) __mingw_vsnprintf(char*, size_t, const char*, __builtin_va_list);
# 376 "c:\\mingw\\include\\stdio.h" 3
extern unsigned int _mingw_output_format_control( unsigned int, unsigned int );
# 453 "c:\\mingw\\include\\stdio.h" 3
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int fprintf (FILE *, const char *, ...);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int printf (const char *, ...);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int sprintf (char *, const char *, ...);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int vfprintf (FILE *, const char *, __builtin_va_list);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int vprintf (const char *, __builtin_va_list);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int vsprintf (char *, const char *, __builtin_va_list);
# 478 "c:\\mingw\\include\\stdio.h" 3
 int __attribute__((__cdecl__)) __attribute__((__nothrow__)) __attribute__((__format__(__ms_printf__,2,3))) __msvcrt_fprintf(FILE *, const char *, ...);
 int __attribute__((__cdecl__)) __attribute__((__nothrow__)) __attribute__((__format__(__ms_printf__,1,2))) __msvcrt_printf(const char *, ...);
 int __attribute__((__cdecl__)) __attribute__((__nothrow__)) __attribute__((__format__(__ms_printf__,2,3))) __msvcrt_sprintf(char *, const char *, ...);
 int __attribute__((__cdecl__)) __attribute__((__nothrow__)) __attribute__((__format__(__ms_printf__,2,0))) __msvcrt_vfprintf(FILE *, const char *, __builtin_va_list);
 int __attribute__((__cdecl__)) __attribute__((__nothrow__)) __attribute__((__format__(__ms_printf__,1,0))) __msvcrt_vprintf(const char *, __builtin_va_list);
 int __attribute__((__cdecl__)) __attribute__((__nothrow__)) __attribute__((__format__(__ms_printf__,2,0))) __msvcrt_vsprintf(char *, const char *, __builtin_va_list);






 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int _snprintf (char *, size_t, const char *, ...);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int _vsnprintf (char *, size_t, const char *, __builtin_va_list);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int _vscprintf (const char *, __builtin_va_list);
# 501 "c:\\mingw\\include\\stdio.h" 3
__attribute__((__cdecl__)) __attribute__((__nothrow__)) __attribute__((__format__(__mingw_printf__,3,4)))
int snprintf (char *, size_t, const char *, ...);

__attribute__((__cdecl__)) __attribute__((__nothrow__)) __attribute__((__format__(__mingw_printf__,3,0)))
int vsnprintf (char *, size_t, const char *, __builtin_va_list);

__attribute__((__cdecl__)) __attribute__((__nothrow__))
int vscanf (const char * __restrict__, __builtin_va_list);

__attribute__((__cdecl__)) __attribute__((__nothrow__))
int vfscanf (FILE * __restrict__, const char * __restrict__, __builtin_va_list);

__attribute__((__cdecl__)) __attribute__((__nothrow__))
int vsscanf (const char * __restrict__, const char * __restrict__, __builtin_va_list);
# 646 "c:\\mingw\\include\\stdio.h" 3
__attribute__((__cdecl__)) __attribute__((__nothrow__)) ssize_t
getdelim (char ** __restrict__, size_t * __restrict__, int, FILE * __restrict__);

__attribute__((__cdecl__)) __attribute__((__nothrow__)) ssize_t
getline (char ** __restrict__, size_t * __restrict__, FILE * __restrict__);
# 666 "c:\\mingw\\include\\stdio.h" 3
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int fscanf (FILE *, const char *, ...);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int scanf (const char *, ...);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int sscanf (const char *, const char *, ...);



 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int fgetc (FILE *);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) char * fgets (char *, int, FILE *);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int fputc (int, FILE *);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int fputs (const char *, FILE *);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) char * gets (char *);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int puts (const char *);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int ungetc (int, FILE *);
# 687 "c:\\mingw\\include\\stdio.h" 3
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int _filbuf (FILE *);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int _flsbuf (int, FILE *);



extern inline __attribute__((__gnu_inline__)) __attribute__((__cdecl__)) __attribute__((__nothrow__)) int getc (FILE *);
extern inline __attribute__((__gnu_inline__)) __attribute__((__cdecl__)) __attribute__((__nothrow__)) int getc (FILE * __F)
{
  return (--__F->_cnt >= 0)
    ? (int) (unsigned char) *__F->_ptr++
    : _filbuf (__F);
}

extern inline __attribute__((__gnu_inline__)) __attribute__((__cdecl__)) __attribute__((__nothrow__)) int putc (int, FILE *);
extern inline __attribute__((__gnu_inline__)) __attribute__((__cdecl__)) __attribute__((__nothrow__)) int putc (int __c, FILE * __F)
{
  return (--__F->_cnt >= 0)
    ? (int) (unsigned char) (*__F->_ptr++ = (char)__c)
    : _flsbuf (__c, __F);
}

extern inline __attribute__((__gnu_inline__)) __attribute__((__cdecl__)) __attribute__((__nothrow__)) int getchar (void);
extern inline __attribute__((__gnu_inline__)) __attribute__((__cdecl__)) __attribute__((__nothrow__)) int getchar (void)
{
  return (--(&_iob[0])->_cnt >= 0)
    ? (int) (unsigned char) *(&_iob[0])->_ptr++
    : _filbuf ((&_iob[0]));
}

extern inline __attribute__((__gnu_inline__)) __attribute__((__cdecl__)) __attribute__((__nothrow__)) int putchar(int);
extern inline __attribute__((__gnu_inline__)) __attribute__((__cdecl__)) __attribute__((__nothrow__)) int putchar(int __c)
{
  return (--(&_iob[1])->_cnt >= 0)
    ? (int) (unsigned char) (*(&_iob[1])->_ptr++ = (char)__c)
    : _flsbuf (__c, (&_iob[1]));}
# 734 "c:\\mingw\\include\\stdio.h" 3
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) size_t fread (void *, size_t, size_t, FILE *);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) size_t fwrite (const void *, size_t, size_t, FILE *);



 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int fseek (FILE *, long, int);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) long ftell (FILE *);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) void rewind (FILE *);
# 787 "c:\\mingw\\include\\stdio.h" 3
typedef long long fpos_t;




 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int fgetpos (FILE *, fpos_t *);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int fsetpos (FILE *, const fpos_t *);



 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int feof (FILE *);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int ferror (FILE *);
# 808 "c:\\mingw\\include\\stdio.h" 3
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) void clearerr (FILE *);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) void perror (const char *);






 __attribute__((__cdecl__)) __attribute__((__nothrow__)) FILE * _popen (const char *, const char *);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int _pclose (FILE *);


 __attribute__((__cdecl__)) __attribute__((__nothrow__)) FILE * popen (const char *, const char *);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int pclose (FILE *);




 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int _flushall (void);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int _fgetchar (void);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int _fputchar (int);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) FILE * _fdopen (int, const char *);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int _fileno (FILE *);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int _fcloseall (void);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) FILE * _fsopen (const char *, const char *, int);

 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int _getmaxstdio (void);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int _setmaxstdio (int);
# 859 "c:\\mingw\\include\\stdio.h" 3
unsigned int __attribute__((__cdecl__)) __mingw_get_output_format (void);
unsigned int __attribute__((__cdecl__)) __mingw_set_output_format (unsigned int);







int __attribute__((__cdecl__)) __mingw_get_printf_count_output (void);
int __attribute__((__cdecl__)) __mingw_set_printf_count_output (int);
# 885 "c:\\mingw\\include\\stdio.h" 3
extern inline __attribute__((__gnu_inline__)) __attribute__((__always_inline__)) unsigned int __attribute__((__cdecl__)) _get_output_format (void)
{ return __mingw_get_output_format (); }

extern inline __attribute__((__gnu_inline__)) __attribute__((__always_inline__)) unsigned int __attribute__((__cdecl__)) _set_output_format (unsigned int __style)
{ return __mingw_set_output_format (__style); }
# 910 "c:\\mingw\\include\\stdio.h" 3
extern inline __attribute__((__gnu_inline__)) __attribute__((__always_inline__)) int __attribute__((__cdecl__)) _get_printf_count_output (void)
{ return 0 ? 1 : __mingw_get_printf_count_output (); }

extern inline __attribute__((__gnu_inline__)) __attribute__((__always_inline__)) int __attribute__((__cdecl__)) _set_printf_count_output (int __mode)
{ return 0 ? 1 : __mingw_set_printf_count_output (__mode); }



 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int fgetchar (void);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int fputchar (int);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) FILE * fdopen (int, const char *);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int fileno (FILE *);
# 930 "c:\\mingw\\include\\stdio.h" 3
extern inline __attribute__((__gnu_inline__)) __attribute__((__always_inline__)) FILE * __attribute__((__cdecl__)) __attribute__((__nothrow__)) fopen64 (const char *, const char *);
extern inline __attribute__((__gnu_inline__)) __attribute__((__always_inline__))
FILE * __attribute__((__cdecl__)) __attribute__((__nothrow__)) fopen64 (const char * filename, const char * mode)
{ return fopen (filename, mode); }

int __attribute__((__cdecl__)) __attribute__((__nothrow__)) fseeko64 (FILE *, __off64_t, int);






extern inline __attribute__((__gnu_inline__)) __attribute__((__always_inline__)) __off64_t __attribute__((__cdecl__)) __attribute__((__nothrow__)) ftello64 (FILE *);
extern inline __attribute__((__gnu_inline__)) __attribute__((__always_inline__))
__off64_t __attribute__((__cdecl__)) __attribute__((__nothrow__)) ftello64 (FILE * stream)
{ fpos_t __pos; return (fgetpos(stream, &__pos)) ? -1LL : (__off64_t)(__pos); }
# 958 "c:\\mingw\\include\\stdio.h" 3
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int fwprintf (FILE *, const wchar_t *, ...);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int wprintf (const wchar_t *, ...);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int vfwprintf (FILE *, const wchar_t *, __builtin_va_list);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int vwprintf (const wchar_t *, __builtin_va_list);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int _snwprintf (wchar_t *, size_t, const wchar_t *, ...);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int _vscwprintf (const wchar_t *, __builtin_va_list);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int _vsnwprintf (wchar_t *, size_t, const wchar_t *, __builtin_va_list);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int fwscanf (FILE *, const wchar_t *, ...);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int wscanf (const wchar_t *, ...);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int swscanf (const wchar_t *, const wchar_t *, ...);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) wint_t fgetwc (FILE *);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) wint_t fputwc (wchar_t, FILE *);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) wint_t ungetwc (wchar_t, FILE *);




 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int swprintf (wchar_t *, const wchar_t *, ...);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int vswprintf (wchar_t *, const wchar_t *, __builtin_va_list);



 __attribute__((__cdecl__)) __attribute__((__nothrow__)) wchar_t * fgetws (wchar_t *, int, FILE *);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int fputws (const wchar_t *, FILE *);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) wint_t getwc (FILE *);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) wint_t getwchar (void);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) wint_t putwc (wint_t, FILE *);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) wint_t putwchar (wint_t);


 __attribute__((__cdecl__)) __attribute__((__nothrow__)) wchar_t * _getws (wchar_t *);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int _putws (const wchar_t *);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) FILE * _wfdopen(int, const wchar_t *);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) FILE * _wfopen (const wchar_t *, const wchar_t *);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) FILE * _wfreopen (const wchar_t *, const wchar_t *, FILE *);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) FILE * _wfsopen (const wchar_t *, const wchar_t *, int);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) wchar_t * _wtmpnam (wchar_t *);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) wchar_t * _wtempnam (const wchar_t *, const wchar_t *);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int _wrename (const wchar_t *, const wchar_t *);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int _wremove (const wchar_t *);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) void _wperror (const wchar_t *);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) FILE * _wpopen (const wchar_t *, const wchar_t *);






__attribute__((__cdecl__)) __attribute__((__nothrow__)) int snwprintf (wchar_t *, size_t, const wchar_t *, ...);
__attribute__((__cdecl__)) __attribute__((__nothrow__)) int vsnwprintf (wchar_t *, size_t, const wchar_t *, __builtin_va_list);
# 1016 "c:\\mingw\\include\\stdio.h" 3
__attribute__((__cdecl__)) __attribute__((__nothrow__)) int vwscanf (const wchar_t *__restrict__, __builtin_va_list);
__attribute__((__cdecl__)) __attribute__((__nothrow__))
int vfwscanf (FILE *__restrict__, const wchar_t *__restrict__, __builtin_va_list);
__attribute__((__cdecl__)) __attribute__((__nothrow__))
int vswscanf (const wchar_t *__restrict__, const wchar_t * __restrict__, __builtin_va_list);






 __attribute__((__cdecl__)) __attribute__((__nothrow__)) FILE * wpopen (const wchar_t *, const wchar_t *);




 __attribute__((__cdecl__)) __attribute__((__nothrow__)) wint_t _fgetwchar (void);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) wint_t _fputwchar (wint_t);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int _getw (FILE *);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int _putw (int, FILE *);




 __attribute__((__cdecl__)) __attribute__((__nothrow__)) wint_t fgetwchar (void);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) wint_t fputwchar (wint_t);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int getw (FILE *);
 __attribute__((__cdecl__)) __attribute__((__nothrow__)) int putw (int, FILE *);





# 2 "hello.c" 2



# 4 "hello.c"
int main ()
{
 int y = 5;

 printf("y = %d ", ((y) + 1));

 return 0;
}
   


what should be observed in this text file
 

Offline golden_labels

  • Super Contributor
  • ***
  • Posts: 1284
  • Country: pl
what should be observed in this text file
The third non-empty line from bottom.
People imagine AI as T1000. What we got so far is glorified T9.
 

Online brucehoult

  • Super Contributor
  • ***
  • Posts: 4207
  • Country: nz
Disagree.
I am 100% convinced that the preprocessor is THE reason that hacky ugly C won out over functionally-equivalent but more "pure" languages such as Pascal.

Your opinion, bus sorry, I don't agree with that.

For me, C flexibility with "data-struct" and "data-union" coupled with more powerful "pointer arithmetic"   is one of *THE* reason whey C is better than Pascal in this specific cases

Pascal has records, variant records, pointers, and the ability to cast between integers and pointers and find the size of objects. It has *exactly* the same capabilities as C in those regards.
 

Online brucehoult

  • Super Contributor
  • ***
  • Posts: 4207
  • Country: nz
Ok, I made the mistake to quickly test them with what I had on my hands, but why are you still here reproach me it was somehow confusing? and can't I express what I honestly think from 25 years of professional programming experience?

I'm not sure that's regarded as being a lot around here :-)

What is "professional", exactly?

I hadn't graduated yet (one more year...), but in 1982 I got paid to spend 10 weeks of my summer vacation writing COBOL (and a bit of FORTRAN) on a PR1ME minicomputer at the Whangarei City Council. I was the only person working on the project and it was successful.

I'm far from the most experienced on this forum ...
 

Online DiTBho

  • Super Contributor
  • ***
  • Posts: 4013
  • Country: gb
Pascal has records, variant records, pointers, and the ability to cast between integers and pointers and find the size of objects. It has *exactly* the same capabilities as C in those regards.

Pascal was my first programming language, and I know in TurboPascal v7 there is no "cast" feature which does this in the compile process like C. In Turbo Pascal there are standard procedures (built-in, or external) which *convert* a type to another type.

That's how the first Pascal works. Call it "unchecked converter" (usually written in Turbo Assembly) and you get exactly what I have always tried to reproduce in every of C projects (in my case, written in C, but segragated outside the project space, so they won't be checked, that's why they are called "unchecked converters").

If comparing pre-C89 to the first Pascal makes sense, then you also have to consider that the second one is more limited because it's more typed, and you cannot directly convert a record (struct) to an other record like with Unions in C, again you need to use "unchecked converters", and that's why I think people prefer C.

Freepascal is the evolution of first Pascal, it adds new features and two flavors of typecasting - implicit typecasting and explicit typecasting, so now you also have - value typecasting - and - variable typecast - but if here it's like comparing c89 with something new, then for example you have to consider that when source’s range of value does not fit into the destination operand’s range, the compiler will not compile the program, unless it is instructed to ignore this, and that exactly what I means: still you desperately need unchecked converters to achieve your purpose.

I think C people are not comfortable with this. When I switched to C I didn't feel it was limiting, but most of my friends left Pascal for this reason.
The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 

Online DiTBho

  • Super Contributor
  • ***
  • Posts: 4013
  • Country: gb
What is "professional", exactly?

I run software testing as part of the product life-cycle; "professional" means I won't get paid until I can prove with facts that a piece of code passes a series of test-cases.

So when I look at a piece of code, I usually care about the possibility to write test cases by exploiting a debugging tool like the ICE: it's theoretically wrong (you cannot test the quality on the product, but) it is a sufficient condition to do my job with the best possible results with the least effort.

If something can be debugged, it can be debugged automatically, then automatically tested with human supervision. I've been doing a lot of weird stuff over the past 15 years, recently I'm writing this kind of testing tools for a living.

When I talked about my hack to Clang, well, that was a prototype that is paying off!
The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 

Online brucehoult

  • Super Contributor
  • ***
  • Posts: 4207
  • Country: nz
Pascal has records, variant records, pointers, and the ability to cast between integers and pointers and find the size of objects. It has *exactly* the same capabilities as C in those regards.

Pascal was my first programming language, and I know in TurboPascal v7 there is no "cast" feature which does this in the compile process like C. In Turbo Pascal there are standard procedures (built-in, or external) which *convert* a type to another type.

I've never used a version of Turbo Pascal as late as v7. I used 1.0 and you could certainly cast between pointers of varying types.

Here is the manual for Turbo Pascal v3. It looks pretty much like what I remember from v1.0.

http://bitsavers.informatik.uni-stuttgart.de/pdf/borland/turbo_pascal/TURBO_Pascal_Reference_Manual_CPM_Version_3_Dec88.pdf

May I refer you to section 22.12.2 "POINTERS AND INTEGERS"?

Quote
The standard functions Ord and Ptr provide direct control of the
address contained in a pointer. Ord returns the address contained in
its pointer argument as an Integer, and Ptr converts its Integer
argument into a pointer which is compatible with all pointer types.

These functions are extremely valuable in the hands of an experienced
programmer as they allow a pointer to point to anywhere in memory.
If used carelessly, however, they are very dangerous, as a dynamic
variable may be made to overwrite other variables, or even program
code.

Also please see 22.8 ADDR FUCNTION

Quote
Syntax: Addr(Name);

Returns the address in memory of the first byte of the type, varialbe,
procedure, or function with the identifier Name. If Name is an array, it
may be subscripted, and if Name is a record, specific fields may be
selected. The value returned is of type Integer.

Also please see 16.3.2.4.8. SIZEOF:

Quote
Syntax: SizeOf(Name);
Returns the number of bytes occupied in memory by the variable or
type Name. The result is of type Integer.

Therefore you can write code such as the following:

Code: [Select]
var
  s : array[1..11] of char;
  p : ^char;

begin
  s := 'Hello World';
  p := Ptr(Addr(s) + 6 * SizeOf(char));
  WriteLn(p^);
end

... and you will see printed "W". And this will work no matter whether Char is 1 or 2 or 4 bytes.

Pascal is functionally *exactly* the same as C in this regard. The only thing different is the exact syntax for achieving it.

I didn't do any DOS or Windows programming, only Apple ][, then PDP-11/VAX and CP/M, and then Macintosh and Unix. EVERY Pascal I used had the ability to do this. The only difference I recall is some used @ instead of Addr.

 

Offline SiliconWizard

  • Super Contributor
  • ***
  • Posts: 14869
  • Country: fr
Oh yeah, now I remember this in TP 3.0 that I used on CP/M. You could even insert assembly code directly in procedures and functions - there was no internal assembler, so you had to list the opcodes, but there was a syntax for putting the address of a parameter or variable directly in the opcodes stream.

The only thing I was really missing in Pascal was the ability to pass functions and procedures as parameters/variables. (I think that was added in TP much later?)
Of course, Wirth added that in Oberon (and maybe Modula, but I admit I don't know Modula well.)

The other thing missing was separate compilation/modules (at least in TP 3.0), but this was added in later versions as "units", which were relatively similar to Modula and Oberon modules. Units were available in the first (and I think only) version of TP for MacOS, that I also used in the early 90's. It was a decent environment to program for MacOS back then. =)
« Last Edit: March 06, 2022, 03:07:41 am by SiliconWizard »
 

Online brucehoult

  • Super Contributor
  • ***
  • Posts: 4207
  • Country: nz
The only thing I was really missing in Pascal was the ability to pass functions and procedures as parameters/variables. (I think that was added in TP much later?)
Of course, Wirth added that in Oberon (and maybe Modula, but I admit I don't know Modula well.)

That has *always* been in Pascal. Maybe TP didn't include it? Borland did have a habit of just leaving stuff out.

See the railway track diagram for Parameter list on p355 of Wirth's 1976 "Algorithms + Data Structures = Programs", which includes "function foo : returnType" or "procedure bar" as items in a parameter list.

http://www.cl72.org/110dataAlgo/Algorithms%20%20%20Data%20Structures%20=%20Programs%20[Wirth%201976-02].pdf

There is, obviously, an un-Worthian lack of type checking in this early version.


Apple's 1980 Apple Pascal Language Reference Manual explicitly states on p87 that it differs from standard Pascal in NOT allowing procedures and functions to be passed as arguments.

https://mirrors.apple2.org.za/Apple%20II%20Documentation%20Project/Software/Languages/Apple%20II%20Pascal/Manuals/Apple%20Pascal%20Language%20Reference%20Manual.pdf

 

Offline Dadu@Topic starter

  • Contributor
  • Posts: 34
  • Country: in
what should be observed in this text file
The third non-empty line from bottom.

hello.c

Code: [Select]
printf("y = %d ", add(y));
text
Code: [Select]

printf("y = %d ", ((y) + 1));

In text file body of add (y) execute

But still there's a lot confusion
 

Online DiTBho

  • Super Contributor
  • ***
  • Posts: 4013
  • Country: gb
But still there's a lot confusion

Precisely. Confusion. Macros are confusing. What did I say from the start?
W-H-A-T?!? :D

The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 

Online DiTBho

  • Super Contributor
  • ***
  • Posts: 4013
  • Country: gb
Quote
The standard functions Ord and Ptr provide direct control of the address contained in a pointer. Ord returns the address contained in its pointer argument as an Integer, and Ptr converts its Integer argument into a pointer which is compatible with all pointer types.

I didn't say there are no pointers, I said there is no easy-Unions like in C, and in general, in Pascal you need more effort to get the same result.

A Pascal-union-like is called "case inside a record", it makes it possible to give a variable multiple types. In this example w1, w2, w3 are stored at the same location in memory:
Code: [Select]
OType = (type1, type2, type3);

OMe = record
  case myType: OType of <-------------- this is a union-like in Pascal
    type1: (w1: Integer);
    type2: (w2: Integer);
    type3: (w3: Integer);
end;

It's not safe, there are Pascal implementations that don't check the simple semantic correctness(1), if you want a "typesafe union", you should use "inheritance", which is a plus for me because it forces you to think twice about what you are doing with the result that it usually makes things cleaner, but not for most people who have switched to C.

Those two standard functions Ord() and Ptr() are exactly what I was talking about when I write "unchecked converters". It's a term I invented to describe things that are somehow part of the language, like "sizeof()" is part of the C language, but they are not written with the same language they belong to as operators/functions, but rather with an external language, usually assembly.



(1) certain implementations don't detect accessing an inactive variant in a case blocks in variant records.
Code: [Select]
var
  O: OMe;
begin
  O.myType := Type1;
  O.w2 := 666; <-------- There is no w2 for Type1, w2 belongs to Type2!
end.
- ISO 7185 Standard Pascal implementations usually care about that
- Turbo Borland Pascal usually don't care about that




« Last Edit: March 06, 2022, 11:26:51 am by DiTBho »
The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 

Online DiTBho

  • Super Contributor
  • ***
  • Posts: 4013
  • Country: gb
@Dadu@
I usually use cpp *only* for two things
  • to define the size of a static array.
  • to define the version and revision of a module

Code: [Select]
#define pool_N  200
pool_item_t pool[pool_N];

#define Ver "v1.0"
#define Rev "revA"

If you look at my topic on complex numbers, well ... this is a nice example of when I say that "macros are like public restrooms, everyone wants to use, nobody (me included) wants to clean". See, glibc adds a lot of Macro layers to describe different kinds of functions, which sounds good to listen to because you have "float atan()", "double atan()", etc ... "type_x func_y()" , but things get so messed up that gcc-v8-v11 is out of the box and nobody in Gentoo wants to clean it up because it would involve a patch to glibc, which is a prohibition since it's too fragile (if you break glibc, the whole system collapses) .

And since I don't like to waste time on that, I had to create an ugly hack to bypass some of those Macros, so things are back working and I can complete my projects.
The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf