C Language Conundrum

WBahn

Joined Mar 31, 2012
32,890
Hi,

So you are saying the original designers of the C language were Gods and never made a mistake? :)
Where the hell did I ever make that claim?

But again we would have to look at some implementations to be sure.
Again, the C language was written specifically with an eye toward being hardware agnostic (which is not to say that it wasn't influenced by the capabilities of the hardware it was being developed on and for).

Again, the C language was written specifically for applications that, at the time, were the almost total and exclusive domain of assembly language because high level languages couldn't produce sufficiently tight code.

Again, the developers of C wanted to place as few restrictions on whoever was implementing a compiler for whatever hardware they were implementing it on so that they would have the opportunity to make it as efficient as possible.

Again, the developers of the C language explicitly recommended that the int data type correspond to the natural data type of the underlying hardware.

So why was it so unreasonable for them to adopt standard library functions (which developed in a hodge-podge manner anyway) that used the int data type as much as possible so as to avoid, as much as possible, denying those very same compiler implementers they ability to exploit the benefits of making the int data type match the natural data type of the underlying hardware?

And, no, regardless of what you keep trying to claim, this does NOT mean that I'm saying that char can't or shouldn't ever be used. I never said that. I never implied that. So let's leave the straw man at home, please.
 

ErnieM

Joined Apr 24, 2011
8,415
However, in this case you are commenting on something i never asked about. It's not about reading the manual that tells you everything you ever wanted to know about anything in the universe and it being 100 percent accurate so you walk away with the mind of God and can therefore do anything and everything possible, it's about glancing at the prototype and being able to understand what arguments the function takes and have a basic understanding of how it will handle them. it is much better practice to pass the type of variable your function needs for that argument. For an example:
memset(void*,int_128 c, int_128 n);

Note in this example we not only cant use the entire range of c, we cant use the entire range of n either.
In a base library language it is slightly different, but i have a feeling it never makes a difference for this particular function.
I am commenting on something you frequently refer to and base your arguments on, and that is using your own judgement as opposed to reading the documentation.

If you think you can build a better function then go do so! Nothing forces you to use the standard library. Nothing!

But if you are going to employ a standard library, then please do take the time to read the standard and not just stand there and try to defend your off the cuff guesses.
 
No. In the earliest standard an int was required to be of such size as to hold positive and negative values that correspond to a 16-bit 2's complement value. I can't absolutely guarantee that this was the case in the very first inception, but it was originally targeted for a 16-bit architecture (the PDP-11, if I'm correct), so not a surprise that the int was 16 bits.



Or, perhaps, we could encourage people to actually look up what a function does before they use it. Just a thought.



An int was NEVER meant to be a specific width. This is true of most of the primitive types in C. There are requirements that it must meet, but it can exceed them and still be perfectly compliant. That's why some machines have 16-bit ints, some have 32-bit ints, and some have 64-bit ints. You have macro constants provided by the compiler to determine what they are on a particular implementation. Even a char is not required to be one byte. Similarly, the source code alphabet is not required to be the same as the execution code alphabet and neither is required to be ASCII. It is only relatively recently that you have standard data types that ARE fixed-width, though most implementations offered them as implementation-specific extensions long ago.



We don't assume. THAT'S the point we have (very unsuccessfully) been trying to get across. We rely on the language standard, which requires that a cast from on integer data type to a smaller integer data type preserves those values that can be represented by both types AND that the representation be the same.
I believe that you are correct. From K&R, 1978....
"int an integer, typically reflecting the natural size of integers on the host machine" p34
This is followed by a chart showing sizes for PDP-11 (16), Honeywell 6000 (36), IBM 370 (32), Interdata 8/32 (32)
and the text - "int will normally reflect the most "natural" size for a particular machine"

and from the preface " C was originally designed for and implemented on the UNIX operating system on the DEC PDP-11, by Dennis Ritchie. The operating system, the C compiler, and essentially all UNIX applications programs (including all of the software used to prepare this book) are written in C. Production compilers also exist for several other machines, including the IBM System/37 the Honeywell 6000, and the Interdata
8/32. C is not tied to any particular hardware or system, however, and it is easy to write programs that will run without change on any machine that supports C."

That was 39 years ago! With the original implementation on a PDP-11 - what, some 5 years earlier? Very cool reading (or re-reading). You really do get the flavor of both the intention and the impact for what these guys did and what C was about..

Now, it is arguably the most used computer language in the world and has been implemented on, I don't know how many platforms and architectures.

But what I really wanted to say was look at this attachment :)... I had some experience programming on both a PDP-8 and a PDP 11/73 with FORTRAN. We used to lock the doors and turn off the lights when the DEC guy came around for "preventive maintenance" because it was likely that they would screw something up and it would cost you the day getting it back. We had state-of-the-art removable hard disks. We would go into mourning when the heads crashed - there was a great deal of mourning. For some reason, I saved the platter from one and have schlepped it around for many years - that is what is in the picture. In the center, there is a 32GB SD card to give you a size reference. Can't remember what they held, likely a heck of a lot less than 32G.

PDPhd IMG_8505.jpg
 
Last edited:

WBahn

Joined Mar 31, 2012
32,890
I believe that you are correct. From K&R, 1978....
"int an integer, typically reflecting the natural size of integers on the host machine" p34
This is followed by a chart showing sizes for PDP-11 (16), Honeywell 6000 (36), IBM 370 (32), Interdata 8/32 (32)
and the text - "int will normally reflect the most "natural" size for a particular machine".
And this was carried forward into the language standard, which states explicitly (Sec 6.2.5 of the N869 C99 Draft Standard), " A ‘‘plain’’ int object has the natural size suggested by the architecture of the execution environment (large enough to contain any value in the range INT_MIN to INT_MAX as defined in the header <limits.h>)." The standard requires that the minimum magnitude of both INT_MIN and INT_MAX be 32,767. Notice that INT_MIN is specifically NOT -32768, which is representable in a 16-bit two's complement representation. This slight difference allows an implementation to use any of several signed-integer representations, including signed-binary, one's compliment, and two's complement. However, the requirement that values representable by both the signed and unsigned data type of the same size share the same representation in both types precludes the use of offset-binary.
 
NO!!!! It is NOT a pointer to bytes!

It is a pointer to data of UNKNOWN type and size! PERIOD! End of sentence.

/--snip-/.
I don''t think that is entirely accurate, at least not the “PERIOD! End of sentence." part.

From the C99 standards, I see…” The use of void* (“pointer to void”) as a generic object pointer type is an invention of the C89 Committee…..

From the C89/90 standards, I see this…” A pointer to void shall have the same representation and alignment requirements as a pointer to a character type. Other pointer types need not have the same representation or alignment requirements.”

I know what you are emphatically saying and it hardly refutes your point, but it seems to me that, technically, there are requirements for a pointer to void and they are, by intention, similar to those of a pointer to a character type.

The only reason I know this is because of a long head-banging session. I was writing a function that I wanted to send both unsigned char * and signed char *.

The compiler would not let me do this by giving me a warning or error along the lines of:
pointer targets in passing argument 1 of 'blahblah' differ in signedness [-Werror=pointer-sign]
because, of course, an unsigned character is a different type than a signed char, even though they were, in my case, always the same size.

I could have turned the error off with some compiler switch, I suppose, but that is always a bad idea for me.

I was not going to write two separate functions and I was also not going to always typecast one or the other (the less typecasting I do, the better).

So, I wrote the function prototype as blah_write(void * message); and it worked just fine. Maybe this was sloppy, but I don't see how, after reading about what the heck a pointer to void was. The function always knew what to do and it was the same thing regardless of whether it was a signed or unsigned char. I believed and still do, that it was the way to go.
 
And this was carried forward into the language standard, which states explicitly (Sec 6.2.5 of the N869 C99 Draft Standard), " A ‘‘plain’’ int object has the natural size suggested by the architecture of the execution environment (large enough to contain any value in the range INT_MIN to INT_MAX as defined in the header <limits.h>)." The standard requires that the minimum magnitude of both INT_MIN and INT_MAX be 32,767. Notice that INT_MIN is specifically NOT -32768, which is representable in a 16-bit two's complement representation. This slight difference allows an implementation to use any of several signed-integer representations, including signed-binary, one's compliment, and two's complement. However, the requirement that values representable by both the signed and unsigned data type of the same size share the same representation in both types precludes the use of offset-binary.
I'm still trying to understand how Honeywell managed to come up with a size of 36.
 

WBahn

Joined Mar 31, 2012
32,890
I'm still trying to understand how Honeywell managed to come up with a size of 36.
That's actually pretty easy.

The "byte" originally referred to the number of bits required to store one character on a machine as this was commonly the smallest amount of addressable memory and/or the smallest data size that could be manipulated directly. The smallest addressable size might be the byte or the "word" (the natural size of the processor), depending on the architecture, but even if it's the word the architecture almost always provides instructions that can act on bytes independent of the other bytes in the word. Lot's of early binary machines used a 6-bit byte. The natural size of the processor was usually chosen to be an integer multiple of this. So there were several 12-bit, 18-bit, 24-bit, and 36-bit machines. While ASCII probably would have moved this to 7-bits, the IBM System/360 came along right on its heals and expanded the character representation to 8-bits and, due to its popularity, that became the de facto definition of a byte at some point (later formalized). The fact that 8 is, itself, an integer power of two almost certainly helped cement that choice.
 

ErnieM

Joined Apr 24, 2011
8,415
@raymond: while a void pointer may have the same representation as a pointer to bytes, it is again NOT a pointer to bytes, at least to my XC8 compiler (C99 compliant). Sorry I cannot post code via my iPad but two identicle functions, one passing a void pointer, one passing a char pointer, yield different results when assigning a character.

The difference being assigning a character yeilds an error "illegal conversion between types."

C has very strong type checking, and type char* is not the same as a void* pointer.
 

WBahn

Joined Mar 31, 2012
32,890
I don''t think that is entirely accurate, at least not the “PERIOD! End of sentence." part.

From the C99 standards, I see…” The use of void* (“pointer to void”) as a generic object pointer type is an invention of the C89 Committee…..

From the C89/90 standards, I see this…” A pointer to void shall have the same representation and alignment requirements as a pointer to a character type. Other pointer types need not have the same representation or alignment requirements.”

I know what you are emphatically saying and it hardly refutes your point, but it seems to me that, technically, there are requirements for a pointer to void and they are, by intention, similar to those of a pointer to a character type.
From the standard: "The void type comprises and empty set of values; it is an incomplete type that cannot be completed."

The size and alignment requirements you speak of do not imply that a void pointer is a pointer to a char. Every data type (and a void pointer is a data type, it just happens to point to data of an unknown type) has to have a specific size and alignment and a void pointer is no exception. In general, there is no requirement that all pointers have the same size and alignment requirements (in order to give the compiler writer the greatest flexibility). But since they have to define something for a void pointer and since, on most architectures, a pointer to a char is the most general pointer in terms of restrictions on size and alignment, they spec'ed that a void pointer must be consistent with that. None of that changes the fact that it is an incomplete type.

The only reason I know this is because of a long head-banging session. I was writing a function that I wanted to send both unsigned char * and signed char *.

The compiler would not let me do this by giving me a warning or error along the lines of:
pointer targets in passing argument 1 of 'blahblah' differ in signedness [-Werror=pointer-sign]
because, of course, an unsigned character is a different type than a signed char, even though they were, in my case, always the same size.
They are ALWAYS the same size. That is required by the standard.

"For each of the signed integer types, there is a corresponding (but different) unsigned integer type (designated with the keyword unsigned) that uses the same amount of storage (including sign information) and has the same alignment requirements."

I could have turned the error off with some compiler switch, I suppose, but that is always a bad idea for me.

I was not going to write two separate functions and I was also not going to always typecast one or the other (the less typecasting I do, the better).

So, I wrote the function prototype as blah_write(void * message); and it worked just fine. Maybe this was sloppy, but I don't see how, after reading about what the heck a pointer to void was. The function always knew what to do and it was the same thing regardless of whether it was a signed or unsigned char. I believed and still do, that it was the way to go.
How did you dereference the 'message' pointer within your blah_write() function? If your compiler is conforming at all, then you should have had to cast it to a pointer to a complete data type. Unless it was ONLY your prototype that had it declared as a void pointer and it was declared as a char (of one type or the other) within the function. Now THAT would have been sloppy!
 

Thread Starter

MrAl

Joined Jun 17, 2014
13,711
I am commenting on something you frequently refer to and base your arguments on, and that is using your own judgement as opposed to reading the documentation.

If you think you can build a better function then go do so! Nothing forces you to use the standard library. Nothing!

But if you are going to employ a standard library, then please do take the time to read the standard and not just stand there and try to defend your off the cuff guesses.
Hi,

Well i could response to this in a number of ways. For one, we could just take everything we hear and read as absolute unchangeable fact, but you can probably see that isnt going to work every time. Sometimes conventions are questioned, and there is good reason for doing that. If we believe everything written down in a manual was written by God (as i was being sarcastic before too) then we would never question it, but being that it is always written by man, sometimes we question it and sometimes there is good reason to do this. I learned this in grammer school when i found errors in math books that were taken as truth for years before that.

Off the cuff guesses? Not all guesses have the same weight. One person's guess could be better than the other, but that's not really what this is about. it's about trying to find out what the difference is between passing two different data types, and how much if any difference there is in today's machines.
Back when C was just starting out they did things differently. Today the only real way to find out is to use statistical time profiling. Of course it's still interesting to see the implementation though, but today that is secondary. I will admit i often forget this myself, but that's the way it is.

Writing my own function, yes i like that idea :)
Here we go:
[sarcasm ON]
char* cmemsetc(char* p,unsigned char c,size_t n)
{
return (char*)memset(p,(int)c,n);
}
[sarcasm OFF]
Now wasnt that fun :)

Another small point is that in C++ if we wrote the function ourselves we could write it as an overloaded function where one uses int c and the other uses char c.
 

Thread Starter

MrAl

Joined Jun 17, 2014
13,711
@raymond: while a void pointer may have the same representation as a pointer to bytes, it is again NOT a pointer to bytes, at least to my XC8 compiler (C99 compliant). Sorry I cannot post code via my iPad but two identicle functions, one passing a void pointer, one passing a char pointer, yield different results when assigning a character.

The difference being assigning a character yeilds an error "illegal conversion between types."

C has very strong type checking, and type char* is not the same as a void* pointer.
Hi again,

The argument i was bringing up was that the void pointer is a pointer to bytes, but you can not use it directly like that in most but not all cases. That's because it is taken as a pointer to bytes with no given structure yet. It's not "UNKNOWN" type though, it's "NOT YET STRUCTURED TYPE", however it still holds a value that points to bytes.
The difference between type unknown and type not_yet_structured is evident in some function calls. If we call it 'unknown' then it sounds like we know nothing about it, when we really do know at least something about it.
 
From the standard: "
....The size and alignment requirements you speak of do not imply that a void pointer is a pointer to a char....

H
Of course, I did not, have not and never will imply that a void pointer is a pointer to a char - no matter how many times I am accused of doing such. I took a solemn oath and I know well the infraction is punishable by law. I noted requirements of pointer to void including the text to a similarity to a pointer to char. Text from the C89/90 standard and a link to where I quoted it from - you know that and I am not going to take every quote that you wrote and do a "why the heck are you saying that, I never said that it did - where in my message did I say that?!" I don't see those exchanges as constructive (see my pvt message).

More to the point that concerns me, is the usage that I mentioned. I do want your opinion and the opinion of knowledgeable others on that issue because I can learn something. Because this is getting off the OP topic, Let me start a separate thread for that....
 

WBahn

Joined Mar 31, 2012
32,890
I'm merely trying to explain why there is the similarity that you spoke of.

But I would say that you were implying that they are the same since you touted an example wherein you claim to have used them as the same and stated that you thought this was proper and good and that it was "the way to go".
 

Thread Starter

MrAl

Joined Jun 17, 2014
13,711
I don''t think that is entirely accurate, at least not the “PERIOD! End of sentence." part.

From the C99 standards, I see…” The use of void* (“pointer to void”) as a generic object pointer type is an invention of the C89 Committee…..

From the C89/90 standards, I see this…” A pointer to void shall have the same representation and alignment requirements as a pointer to a character type. Other pointer types need not have the same representation or alignment requirements.”

I know what you are emphatically saying and it hardly refutes your point, but it seems to me that, technically, there are requirements for a pointer to void and they are, by intention, similar to those of a pointer to a character type.

The only reason I know this is because of a long head-banging session. I was writing a function that I wanted to send both unsigned char * and signed char *.

The compiler would not let me do this by giving me a warning or error along the lines of:
pointer targets in passing argument 1 of 'blahblah' differ in signedness [-Werror=pointer-sign]
because, of course, an unsigned character is a different type than a signed char, even though they were, in my case, always the same size.

I could have turned the error off with some compiler switch, I suppose, but that is always a bad idea for me.

I was not going to write two separate functions and I was also not going to always typecast one or the other (the less typecasting I do, the better).

So, I wrote the function prototype as blah_write(void * message); and it worked just fine. Maybe this was sloppy, but I don't see how, after reading about what the heck a pointer to void was. The function always knew what to do and it was the same thing regardless of whether it was a signed or unsigned char. I believed and still do, that it was the way to go.
Hi there,

Interesting to see it written out like that. So they wanted it to be similar to a pointer to bytes. This becomes even more obvious when we take a brief look at the function of main concern in this thread:
void* memset(void* p,int c,size_t n)

Now isnt it true that i can do this:
char p[8];
or this:
int p(8);

and then do this with either one of those:
memset(p,2,8);

and it will at least accept that as valid even though in the second case only two int's get set.
In either case though, it is BYTES that set set, not an UNKNOWN type.
Using type int and reading the first 'int' displays this result:
0x02020202

LOW AND BEHOLD it set BYTES. What a miracle of nature :)
 

WBahn

Joined Mar 31, 2012
32,890
It sets bytes ONLY because the void pointer that is passed in is CAST accordingly INSIDE the function -- the person that wrote the code in the function CHOSE to treat the void pointer as a pointer to a block of bytes and then explicitly cast in accordance with that choice. It has NOTHING to do with a void pointer somehow being a pointer to bytes.

Consider the following code

Code:
#include <stdio.h>
#include <stdlib.h>

void *intset(void *p, char c, size_t n)
{
  size_t i;

  for (i = 0; i < n; i++)
  {
  *(int *)p = c;
  p = (int *)p + 1;
  }

  return p;
}

int main(void)
{
  int i;
  char fred[20];

  for (i = 0; i < 20; i++)
    fred[i] = -1;

  intset(fred, 42, 4);

  for (i = 0; i < 20; i++)
    printf("fred[%i] = %i\n", i, fred[i]);


  return EXIT_SUCCESS;
}
If you run this, you get the following:

Code:
fred[0] = 42
fred[1] = 0
fred[2] = 0
fred[3] = 0
fred[4] = 42
fred[5] = 0
fred[6] = 0
fred[7] = 0
fred[8] = 42
fred[9] = 0
fred[10] = 0
fred[11] = 0
fred[12] = 42
fred[13] = 0
fred[14] = 0
fred[15] = 0
fred[16] = -1
fred[17] = -1
fred[18] = -1
fred[19] = -1
As you can see, the void pointer is acting like a pointer to a four byte int. Does that somehow justify someone claiming that, because of how this function behaves, that a void pointer is really a pointer to an int?

Of course not! It is how THIS function was written to TREAT that pointer -- namely it CAST it to pointer that is a complete type.
 
From the standard: "The void type comprises and empty set of values; it is an incomplete type that cannot be completed."

The size and alignment requirements you speak of do not imply that a void pointer is a pointer to a char. Every data type (and a void pointer is a data type, it just happens to point to data of an unknown type) has to have a specific size and alignment and a void pointer is no exception. In general, there is no requirement that all pointers have the same size and alignment requirements (in order to give the compiler writer the greatest flexibility). But since they have to define something for a void pointer and since, on most architectures, a pointer to a char is the most general pointer in terms of restrictions on size and alignment, they spec'ed that a void pointer must be consistent with that. None of that changes the fact that it is an incomplete type.


They are ALWAYS the same size. That is required by the standard.

"For each of the signed integer types, there is a corresponding (but different) unsigned integer type (designated with the keyword unsigned) that uses the same amount of storage (including sign information) and has the same alignment requirements."



How did you dereference the 'message' pointer within your blah_write() function? If your compiler is conforming at all, then you should have had to cast it to a pointer to a complete data type. Unless it was ONLY your prototype that had it declared as a void pointer and it was declared as a char (of one type or the other) within the function. Now THAT would have been sloppy!
Hi there,

Interesting to see it written out like that. So they wanted it to be similar to a pointer to bytes. This becomes even more obvious when we take a brief look at the function of main concern in this thread:
void* memset(void* p,int c,size_t n)

Now isnt it true that i can do this:
char p[8];
or this:
int p(8);

and then do this with either one of those:
memset(p,2,8);

and it will at least accept that as valid even though in the second case only two int's get set.
In either case though, it is BYTES that set set, not an UNKNOWN type.
Using type int and reading the first 'int' displays this result:
0x02020202

LOW AND BEHOLD it set BYTES. What a miracle of nature :)
No freaking way I am getting into that. But look, I have enjoyed this post and it is not that I don't think you have made some points, but I have to tell you (well I don't have to but I kind of want to), and forgive me if it is a bit harsh, the attitude that you have sometimes communicated in this thread are problematic in my view. It is a bit off-putting. As has already been stated, you basically have two choices - do it yourself or make use of what someone else has done. You sometimes act like there is a third choice which is something like - they should have done it the way I want it done, and that is simply not viable. Additionally, in my view, you are grossly under appreciating the evolution of the language.

You may, indeed, have some decent points about memset, but you are making them while basically insulting the writers, and I can't seem to get past that. Look here for a critical opinion on memset. See how clearly the arguments are presented? Frankly, it is easy for me to admit that I am not an expert C programmer who can not continue to learn and get better. There certainly are those with more expertise than I on this board and I am not inclined to try and opine on that critical opinion - in fact, I am distinctly disinterested in doing so. But my point is to contrast the stark difference between the way it is treated in that piece with your presentation, which right out of the starting box seemed to have a "they don't know what they are doing" attitude.
 
I'm merely trying to explain why there is the similarity that you spoke of.

But I would say that you were implying that they are the same since you touted an example wherein you claim to have used them as the same and stated that you thought this was proper and good and that it was "the way to go".
While I respect your explanation for the designer's use of the requirement in the standard, I do not agree at all with your conclusion concerning what I was or was not implying .Stating that I was implying that "they are the same" is analogous to saying that I implied that apples are the same as oranges because Joe can eat them both. If I though that they were the same, I would have no difficulty stating as much and no difficulty being corrected, but as I have now said repeatedly, I do not think they are the same - no matter how many times that you say that I do.

An example of what I was referring to is now posted and I welcome the expertise of yourself as well as anyone else on that issue regarding the specific questions that I raised in the post.
 

WBahn

Joined Mar 31, 2012
32,890
So, let me rephrase what I think you were implying: "No, they are not the same. No, I don't think they are the same. But I can and do use them as if they are the same. I think this is fine and good."

Okay, go right ahead and use them as if they are the same. If and when that bites you, you will learn something that you didn't know before -- that's how most of us learn a lot of what we know.

I would still be interested in seeing ANY code that lets you use a void pointer like a pointer to a char (or ANY thing). I'm not saying that such compilers don't exist, but if they do they are either (a) using a non-standard extension to the language, or (b) incorrectly implementing the standard. There are plenty of compilers (most, actually) that implement extensions. But there is really no point taking the behavior under those extensions because then no meaningful discussion can be had (unless, of course, the point of the discussion is the extension itself).
 

Thread Starter

MrAl

Joined Jun 17, 2014
13,711
No freaking way I am getting into that. But look, I have enjoyed this post and it is not that I don't think you have made some points, but I have to tell you (well I don't have to but I kind of want to), and forgive me if it is a bit harsh, the attitude that you have sometimes communicated in this thread are problematic in my view. It is a bit off-putting. As has already been stated, you basically have two choices - do it yourself or make use of what someone else has done. You sometimes act like there is a third choice which is something like - they should have done it the way I want it done, and that is simply not viable. Additionally, in my view, you are grossly under appreciating the evolution of the language.

You may, indeed, have some decent points about memset, but you are making them while basically insulting the writers, and I can't seem to get past that. Look here for a critical opinion on memset. See how clearly the arguments are presented? Frankly, it is easy for me to admit that I am not an expert C programmer who can not continue to learn and get better. There certainly are those with more expertise than I on this board and I am not inclined to try and opine on that critical opinion - in fact, I am distinctly disinterested in doing so. But my point is to contrast the stark difference between the way it is treated in that piece with your presentation, which right out of the starting box seemed to have a "they don't know what they are doing" attitude.
Hi,

Well i dont know about you but i never told the 'writers' about this. Did you?
Thus, the judgement whether or not they are to be insulted (future tense) remains to be seen. If we found reason to maybe we would, but maybe i would end up being the one insulted.
In other words, the thread is an ongoing work dedicated to uncovering anything that might be wrong, or on the contrary prove everything right. If we proved everything right there would be no reason for insult.
However, the above still pivots on the premise that the so called writers should have foreseen every possible change in computer technology to come from then to the year 3000, which nobody here has made claim to. I had agreed that in the past it might have been viewed as a good choice and maybe even today (although i doubt that in wont argue that point).
It appears that they came up with a better alternative to memset in that link? Gee i am so surprised :)

However, i have seen too many problems in computer related technology to take the option of never questioning anything and that certainly includes things from the past. You can personally agree or disagree, but if you would rather insult me instead that's your choice.

Without going back there then, in today's computer it wont make a smidget of a difference in execution speed and you dont have to agree with that, but before you reject it i suggest you look into time profiling on modern machines. Modern CPU's are very different than the old ones were.

So i defer any insulting of any writers of the language just to be clear until such time that it would make sense to do so, and then i would leave that to someone else to do :)

Back to an interesting set of examples now...

//what seems like a memset equivalent:
void* memset(void *p, int c, size_t n)
{
for(k=0;k<n;k++)
(char*)p[k]=(char)c;
return p;
}
int p[8]={0,0,0,0,0,0,0,0};
p=memset(p,2,8*4); //use the function to set byte values to 2.

//another version:
char* memset(char* p,char c,size_t n)
{
for(k=0;k<n;k++
p[k]=c;
return p
}
int p[8]={0,0,0,0,0,0,0,0};
p=(int*)memset((char*)p,2,8*4);

There is a comparison of two different ways of writing that function and so the calling of it is different too. In the second example we cast the pointer ourselves and of course remove the requirement for the function to have to cast what must be a char in the first place. Clearly there is a difference, but in a modern machine these would execute in a time period that depended not only on those two function but on other code near those binaries.

Note i am not saying that we should purposely insert nop's into code (ha ha) just because it wont make much difference.

The most important aspect of this thread though is what to tell people that are just starting to program in C when this question comes up. "Read the instructions" apparently does not work all the time.
The best answer so far seems to be that the original writers thought that it would make a difference in some code to use type int for the "int c" part, and that the function itself for some reason should have to do an internal cast to char pointer rather than the caller.
 
Last edited:

Thread Starter

MrAl

Joined Jun 17, 2014
13,711
Hello again,

I was thinking about it and i noticed that some people had different ideas and seemed to get irritated over some of the opinions so i think we've talked this though enough.

I do appreciate everyone's input though regardless whether or not that input was pro or con. It was still interesting to talk about.

Thanks, and take care,
MrAl
 
Top