Author Topic: Pointer confusion in C -language  (Read 22256 times)

0 Members and 1 Guest are viewing this topic.

Online SiliconWizard

  • Super Contributor
  • ***
  • Posts: 14553
  • Country: fr
Re: Pointer confusion in C -language
« Reply #125 on: June 28, 2021, 06:12:09 pm »
Quote
- The sizeof operator gives you the size of the allocated memory;

Tells you the size of the element too.

Like 'sizeof(array[0])'.

But, you also get that with a pointer: 'sizeof(*pointer)'. Note that 'sizeof(pointer[0]') would also work.

So, nothing specific to arrays with this. Of course the only pointers you can't get the size of the pointed-to type from are pointers to void. And of course, you can't declare an array of void.
 

Offline Nominal Animal

  • Super Contributor
  • ***
  • Posts: 6321
  • Country: fi
    • My home page and email address
Re: Pointer confusion in C -language
« Reply #126 on: June 28, 2021, 07:28:08 pm »
Y'know, I do actually know how virtual memory works.
I know, and you know I know; I've said so in other threads.

I am trying to make the argument understandable to anyone encountering this issue, and not "elevate" it into technical jargon only those with a minimum of two decades of practical experience, plus at least one decade of research and development, have.

If you think of a way how I could do the above and avoid be taken as implicitly denigrating your or anyone elses skills or experiences, let me know.  I'll pay cash for that advice.

I already know that if I use self-deprecating language, that just causes everybody to ignore what I say, because they take humility for uncertainty or weakness.
At least when they get annoyed, there is still at least a possibility of two-sided communication.  So, better to err on the side of friction, but keep reminding others it is only to try and keep learners in tow (or at least theoretically possible to follow the discussion even if details are hazy), I think; I loved to do that when I was a learner, and it was often invaluable.

I have already mentioned elsewhere on this forum that I never, ever "talk down"; that is a nasty social trick I absolutely detest, and I don't do those.  I'd rather chew off my own foot and eat it raw.  If I sound like "talking down", it is because I don't have the kind of command of English that I sometimes may appear:  I do spend a lot of effort (and post-submit edits after re-reading my own posts to see if I still believe I managed to convey the idea or not).  Not backed by skill, only by sheer hard effort.

I do avoid, hard, jargon language, and repeat known facts like the definitions of concepts, because I don't want to be one of those snobs who think newbies are not worth listening to or talking to just because they don't know the jargon and exact terms to use to sound "professional".

If you feel slighted, I do apologise.  No slight or aspersions of any kind was ever intended on my part.

Same applies to Ataradov and dunkemhigh.  I am genuinely puzzled as to their opinions, because I do value their skills, highly, but I seem to be observing contradictions between their suggestions and their stated design goals.  I feel I do need to be pushy rather than placating here, because being placating will be misunderstood as subservience or uncertainty or tacit admission of some kind of personal or social error; but what I want, is to drag out the reasoning and experiences behind the opinions.  Those are always informative, interesting, and useful.

My point is that on a 16 or 32 bit machine you can very quickly run out of VIRTUAL address space. You have to manage it.
Yes, for sure.  100% in agreement here.

When I read your "Appropriately sizing one stack per thread can be a challenge. Figuring out the right size for *two* stacks per thread, and the balance between them, just seems harder." response, it seemed to me you did not consider the resource savings achievable in reality.

After reading your above post, it appears to me that your underlying argument is something along the lines of "address space policy is complicated, difficult, and fragile; and in my experience, doubling the number of regions involved in such policy can make things untenable".

I obviously agree with that.  But running out address space is not the problem at hand on 48-64 bit address space architectures, where the provisioning problems this could help with are common.

I outlined the scenario where a typical virtualized hosting environment (AMD64, 2GB RAM) is limited to an artificially low number of processes and threads, because having their entire stacks mapped (instead of just "reserved" somehow without actual mappings) means we need to either risk high overcommit ratios (that tend to be unstable because of how they behave in sudden increases in connection attempts et cetera), or pay real money to overprovision the server.

Anyway, I do understand it is also difficult to track my stack-related suggestions and descriptions, when they range from embedded (stack pointer relative effective address checking) to 64-bit only (dealing with correctly provisioning services and virtualized systems, when the prevailing programming paradigm is "just throw more memory and/or more CPU cores at it and it'll work fine") in the very same thread.  Sorry about that.
 

Offline TheCalligrapher

  • Regular Contributor
  • *
  • Posts: 151
  • Country: us
Re: Pointer confusion in C -language
« Reply #127 on: June 29, 2021, 12:49:21 am »
Bruce is right: in C, accessing arrays is implemented in totally the same way as any pointer.

That's is absolutely incorrect. The "pointer" in array access semantics is purely an imaginary concept. It does not exist in reality, meaning that it does not exist as an lvalue. This alone already overturns the claim that array is accessed "the same way as any pointer".

The only extra things an array gives you:
- Static allocation (that's not linked to how they are accessed);

That's false. Array is not a pointer that points to statically allocated memory, if that's what you mean.

- The sizeof operator gives you the size of the allocated memory;

That's false. `sizeof` never works with any kind of "memory" and has no relation to "memory" at all. `sizeof` works with types, types and only types. Both forms of `sizeof` are, by definition, funneled into working with the type supplied as an argument (in one way or another).

When `sizeof` is applied to an array, it returns the size of the array type. Array types are regular types in C. No "pointers" of any kind is involved here. No "allocated memory" is involved either. Note that this is also true when `sizeof` is applied to an VLA.

If you exclude the last point, which is clearly non-standard, there is no difference how access is done between an array and a pointer.

That's is false. One can clam that array access is equivalent to rvalue pointer access, rvalue being the critical detail here. But without it, the above statement is patently false.
 

Offline TheCalligrapher

  • Regular Contributor
  • *
  • Posts: 151
  • Country: us
Re: Pointer confusion in C -language
« Reply #128 on: June 29, 2021, 01:02:37 am »
But C doesn't support arrays at all, whether fixed or variable length.
Sure. Because C "arrays" in general are not arrays, but only allocating space and pointing at it.

Here we go. This popular confusion is the root of the above incorrect claims.

I suggest you read Dennis Ritchie's "The Development of the C Language" article (https://www.bell-labs.com/usr/dmr/www/chist.html), where he describes the decisions he made when developing the idea of arrays in C. Specifically, in that article he explains why he decided to abandon the BCPL's "only allocating space and pointing at it" approach as completely unacceptable for C.

He also explains why arrays in C tend to "mimic" BCPL's behavior, pretending to act as pointers in some contexts. Yet, this simple and rather easily understood "mimicking" behavior managed to confuse quite a few people down the road, who for some reason managed to trap themselves in a silly belief that arrays in C are "only allocating space and pointing at it".

« Last Edit: June 29, 2021, 01:07:51 am by TheCalligrapher »
 

Offline hamster_nz

  • Super Contributor
  • ***
  • Posts: 2803
  • Country: nz
Re: Pointer confusion in C -language
« Reply #129 on: June 29, 2021, 01:54:47 am »
But C doesn't support arrays at all, whether fixed or variable length.
Sure. Because C "arrays" in general are not arrays, but only allocating space and pointing at it.

Here we go. This popular confusion is the root of the above incorrect claims.

I suggest you read Dennis Ritchie's "The Development of the C Language" article (https://www.bell-labs.com/usr/dmr/www/chist.html), where he describes the decisions he made when developing the idea of arrays in C. Specifically, in that article he explains why he decided to abandon the BCPL's "only allocating space and pointing at it" approach as completely unacceptable for C.

He also explains why arrays in C tend to "mimic" BCPL's behavior, pretending to act as pointers in some contexts. Yet, this simple and rather easily understood "mimicking" behavior managed to confuse quite a few people down the road, who for some reason managed to trap themselves in a silly belief that arrays in C are "only allocating space and pointing at it".

I think partially Bruce was baiting me in a friendly way, and partially what he says is true.

C doesn't have "high functioning" arrays, the type that allow you to append, insert or delete items.

And because of C arrays so easily decays into a pointer it is hardly like they are there at all as the information about the size of the array is so quickly lost. All you have to do is call a function or return and it is gone, and that array is now a pointer that points to an unknown number of items.
« Last Edit: June 29, 2021, 01:56:23 am by hamster_nz »
Gaze not into the abyss, lest you become recognized as an abyss domain expert, and they expect you keep gazing into the damn thing.
 

Offline gf

  • Super Contributor
  • ***
  • Posts: 1245
  • Country: de
Re: Pointer confusion in C -language
« Reply #130 on: June 29, 2021, 07:42:10 am »
Quote
C doesn't have "high functioning" arrays, the type that allow you to append, insert or delete items.

The term "varialbe-length array" is indeed a bit misleading. Once a VLA has been allocated (in the stack frame, at runtime), its size still remains fixed. The size just isn't a copile-time constant.
 

Offline DiTBho

  • Super Contributor
  • ***
  • Posts: 3918
  • Country: gb
Re: Pointer confusion in C -language
« Reply #131 on: June 29, 2021, 09:35:27 am »
Arrays are not "objects".
In C there are no "objects".
To be an "object", an array should have
- methods
- identifier
- auto pointer (this)

In C a lists are a "construct" of the language, with some properties like
- data alignment
- data stuffing
- data size

But for example there is no "+=" method to append an item to the tail of the list, neither there is a method to sort or reverse the order of the list.

Yesterday I wrote an A* algorithm in C for a micro-robotic application, the A* is a sub-optimal path finder, you can use it to help your robot to better manage its motion planning. My robot is happy to have a new LiDAR, a RAMSAC algorithm, and this new A* algorithm, but personally for all of these things, especially with the A*, I suffered the lack of some good "lists object" with proper methods to manage items, and I had to implement everything by myself.

Not to mention that my algorithm is polymorphic, I have to fit "lists" of different types, those of LiDAR are different from those of A *, and those of the RAMSAC algorithm are also different, but all these lists must remain in a super binder called "motion-list", and once again I had to implement a wild polymorphism by hand since this is another thing that doesn't exist in C.

If the C language supported objects, lists would be objects, and if lists were objects I would also have the polymorphism ready.

You may wonder, so why didn't you use C++? Well ... good question, long story on the reasons  :D
The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 

Offline DiTBho

  • Super Contributor
  • ***
  • Posts: 3918
  • Country: gb
Re: Pointer confusion in C -language
« Reply #132 on: June 29, 2021, 09:48:27 am »
the type supplied as an argument (in one way or another).

It was decomissioned years ago since more than obsolete, but with my old Avoget compiler, it was the linker who knew and used this information, and the type size of everything was stored into specific fields within the ".o" file and used only in linking stage.

I mean, when I deassembled ".o" files, I always saw an header with the sizeof(everything), but in the .section code area, the sizeof(something ) was always left "to be completed in  linking stage".

Never tried with Gcc, anyway  :-//
The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 

Offline DiTBho

  • Super Contributor
  • ***
  • Posts: 3918
  • Country: gb
Re: Pointer confusion in C -language
« Reply #133 on: June 29, 2021, 10:02:15 am »
He also explains why arrays in C tend to "mimic" BCPL's behavior, pretending to act as pointers in some contexts. Yet, this simple and rather easily understood "mimicking" behavior managed to confuse quite a few people down the road, who for some reason managed to trap themselves in a silly belief that arrays in C are "only allocating space and pointing at it".

You didn't explain why it should be "silly", while my Avoget compiler does exactly that  :-//

When I declare an array in C and look at the produced assembly, I see
- declare the array as "uninitialized" or "initialized"
- reserve space in the proper section (here, "initialized" could mean "constant pool")
- report the array name, its size, and it's address into the object file

Exactly: space allocation, possibly filled with pre-initialized data, and pointing
The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 

Offline PlainName

  • Super Contributor
  • ***
  • Posts: 6871
  • Country: va
Re: Pointer confusion in C -language
« Reply #134 on: June 29, 2021, 10:19:37 am »
Quote
hen I declare an array in C and look at the produced assembly, I see

In this context, surely what is produced as assembler is irrelevant. C is not assembler, just as an engine is not a lump of aluminium, and EEVBlog is not a database.
 

Offline gf

  • Super Contributor
  • ***
  • Posts: 1245
  • Country: de
Re: Pointer confusion in C -language
« Reply #135 on: June 29, 2021, 10:24:17 am »

Quote from: DiTBho
In C there are no "objects".

In C, an "object" is defined as "region of data storage in the execution environment, the contents of which can represent values"

the type supplied as an argument (in one way or another).

It was decomissioned years ago since more than obsolete, but with my old Avoget compiler, it was the linker who knew and used this information, and the type size of everything was stored into specific fields within the ".o" file and used only in linking stage.

I mean, when I deassembled ".o" files, I always saw an header with the sizeof(everything), but in the .section code area, the sizeof(something ) was always left "to be completed in  linking stage".

Never tried with Gcc, anyway  :-//

The sizeof operator is an operator of the C language. It has nothing to do with the linker. Except for variable-length arrays, sizeof(type) or sizeof(expression) is generally a constant C expression, which is known at compile-time. And for VLAs, the size is not known at link time either, but only at runtime.
 

Offline golden_labels

  • Super Contributor
  • ***
  • Posts: 1227
  • Country: pl
Re: Pointer confusion in C -language
« Reply #136 on: June 29, 2021, 10:31:35 am »
Arrays are not "objects".
In C there are no "objects".
Really? Damnit, someone should tell everyone who was involved in creation of the C language — starting from Kerninghan and Ritchie themselves — that they don’t know the language they have defined. Explain to them, how there are no objects, because the language lacks some syntactic sugar! </sarcasm>

Or — that will probably be a better idea — learn the actual abstract machine the C language models.
People imagine AI as T1000. What we got so far is glorified T9.
 

Offline DiTBho

  • Super Contributor
  • ***
  • Posts: 3918
  • Country: gb
Re: Pointer confusion in C -language
« Reply #137 on: June 29, 2021, 11:39:00 am »
In this context, surely what is produced as assembler is irrelevant.

For me it's the *ONLY* thing that really matters.
The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 

Offline DiTBho

  • Super Contributor
  • ***
  • Posts: 3918
  • Country: gb
Re: Pointer confusion in C -language
« Reply #138 on: June 29, 2021, 11:57:40 am »
Yup, Gcc does it differently than Avoget does

Code: [Select]
#define my_array_t_size 32
typedef uint8_t my_array_t[my_array_t_size];

...

   my_array_t my_array;
   console_out_nl("sizeof(my_array)=%ld",sizeof(my_array));


Code: [Select]
...
        stmfd   sp!, {fp, lr}
        add     fp, sp, #4
        sub     sp, sp, #32
        ldr     r0, .L3
        mov     r1, #32 <---------------- sizeof(my_array) = 32, it's known at compile time!!! WOW!!!
        bl      console_out_nl
        sub     sp, fp, #4
        ldmfd   sp!, {fp, pc}
...

.l3:
        .ascii  "sizeof(my_array)=%ld\012\000"
(gcc-armv5tel)
« Last Edit: June 29, 2021, 12:28:56 pm by DiTBho »
The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 

Offline PlainName

  • Super Contributor
  • ***
  • Posts: 6871
  • Country: va
Re: Pointer confusion in C -language
« Reply #139 on: June 29, 2021, 12:23:52 pm »
In this context, surely what is produced as assembler is irrelevant.

For me it's the *ONLY* thing that really matters.

Sure, but only in the assembler context. For all the language cares, an array could resolve to a box of jellybeans so long as it acts like an array should. Thus a pointer in assembler is as meaningless to the C language as would be a homing pigeon carrying a bit of paper.
 

Offline Nominal Animal

  • Super Contributor
  • ***
  • Posts: 6321
  • Country: fi
    • My home page and email address
Re: Pointer confusion in C -language
« Reply #140 on: June 29, 2021, 12:32:13 pm »
In C there are no "objects".
object ≢ object.

See e.g. n1570 (final draft of the C11 standard).  In that context, "object" is not the same "object" that say C11++ uses.

I've been very amazed to see exactly the kind of approaches to pointers in this thread that I keep seeing leading to horribly hard to fix bugs in the real life.  I guess I shouldn't be, because the root cause is NOT a technical problem or definition, but a simple human one.  The compilers are not the cause of most buffer/object overflow/underflow bugs –– I don't actually recall any ––, we humans are.  To change that, we need to change how we think and use pointers to express our ideas.  "Just don't do that then" won't work; we're already at the proverbial doctor's office, and simply "avoid writing buggy code" is unrealistic.  Thus, the "mind over" hyperbole.

It is not just programming, though. In physics, it is at the core of whether one can apply their "knowledge" to solve new types of problems or not; whether their "knowledge" integrates with their other "knowledge" or just stays as separate never-interacting blobbets.  Just read any of my posts in the physics question thread in the chat section; they deal with exactly this, just in physics.  (And "knowledge" itself is a damnably hard concept, because you can "know" something because you have repeated it so many times by rote it is now handled by your autonomous nervous system –– like bike riding; I definitely call it "knowing how to ride a bike" –– or you can "know" how something happens and why, but have difficult expressing it to others because you don't know any/all the words to express those concepts properly.  I was 14 or so when I described to a physicist my idea of using at least two lasers in a transparent box to excite atoms of the enclosed gas in multiple stages, so that only the atoms at the intersection of those lasers would be excited enough to emit visible light. (I had just learned the very, very basics of how lasers work, and was looking at reference data in an effort to see if a suitable gas was already known (with metastable excitation states in infrared, and one or more within visible light, that could be cascaded with those lasers), especially hoping for nitrogen to be viable here.  I was damned lucky, and instead of laughing at me, the physicist talked to me for a good couple of hours about the practical issues, told me the keywords I'd need to look up and understand, and even gave me a couple of trade magazines about lasers he had lying around.  I want to be like him myself.  A few years later, a sharp young lady at MIT did exactly that as their graduate thesis – except of course where I just had a kids' idea without any fixed form or understanding of the whole, just a vague idea, she did both the theory and a practical implementation.  I just don't remember whether she managed to do it in nitrogen (air), or whether she had to use some other gas.)

No, this isn't holography; it is just laser-induced light-emitting true 3D display tech.  While it was demonstrated in practice over 20 years ago, I do not believe even militaries use it today, although it does work, and looks better than those "flickering holograms" with occasional shear plane errors you see in movies.  Works as a high-power space heater, too.
« Last Edit: June 29, 2021, 12:38:25 pm by Nominal Animal »
 
The following users thanked this post: DiTBho

Offline gf

  • Super Contributor
  • ***
  • Posts: 1245
  • Country: de
Re: Pointer confusion in C -language
« Reply #141 on: June 29, 2021, 01:07:05 pm »
Yup, Gcc does it differently than Avoget does

The assembly/object code generated by the compiler certainly matters when platform-specific issues like interfacing, ABI, or performance issues, or similar stuff is considered.
From the abstract point of view, you rather treat the compiled code as black box which is supposed to do (according to the semantics of the C language) what you have written in your C program -- regardless how the compiler achieves this goal.
 
The following users thanked this post: DiTBho

Online SiliconWizard

  • Super Contributor
  • ***
  • Posts: 14553
  • Country: fr
Re: Pointer confusion in C -language
« Reply #142 on: June 29, 2021, 05:44:47 pm »
Bruce is right: in C, accessing arrays is implemented in totally the same way as any pointer.

That's is absolutely incorrect. The "pointer" in array access semantics is purely an imaginary concept. It does not exist in reality, meaning that it does not exist as an lvalue. This alone already overturns the claim that array is accessed "the same way as any pointer".

The only extra things an array gives you:
- Static allocation (that's not linked to how they are accessed);

That's false. Array is not a pointer that points to statically allocated memory, if that's what you mean.

- The sizeof operator gives you the size of the allocated memory;

That's false. `sizeof` never works with any kind of "memory" and has no relation to "memory" at all. `sizeof` works with types, types and only types. Both forms of `sizeof` are, by definition, funneled into working with the type supplied as an argument (in one way or another).

When `sizeof` is applied to an array, it returns the size of the array type. Array types are regular types in C. No "pointers" of any kind is involved here. No "allocated memory" is involved either. Note that this is also true when `sizeof` is applied to an VLA.

If you exclude the last point, which is clearly non-standard, there is no difference how access is done between an array and a pointer.

That's is false. One can clam that array access is equivalent to rvalue pointer access, rvalue being the critical detail here. But without it, the above statement is patently false.

Not sure what all this pile of crap means. A lot of words, but I haven't seen any concrete argument that would actually make my few above points "false".
Like, a pointer for array access 'an imaginary concept"? Do you actually know what a compiler emits for array access? How is that different from pointers (except for the few points I mentioned)? And as I said, except for exotic compiler extensions, the compiled code for accessing an array is no different from doing this directly with a pointer. You can of course assign arrays to pointers for accessing them, and it makes no difference either.

Or possibly you're being overly pedantic to the point of expressing worthless points that can only confuse people instead or helping them.

To make things very clear, I'm strictly talking about C here. C++ is completely different. In C++ you can even overload the [] operator, so that's a completely different territory.

Arrays in C are just effectively allocated memory buffers, whether statically or on the stack.
And then, as obviously a different type that pointers themselves, you get some compiler checks and extensions if any. Nothing more. As I clearly said, of course an array identifier is NOT a pointer. But for accessing its content, it makes no difference. If you think it does, will you please show us how.

Accessing an array in my world (maybe yours is in a different elevated sphere) means: accessing data within it. Which works exactly the same as with any other memory buffer. (Again as I said, you may get some static analysis checks if your compilers have them that can't be done with pointers. But static checks are just static checks.)

Of course an array identifier can't be an l-value, just like a constant pointer. Just like functions.
 

Online SiliconWizard

  • Super Contributor
  • ***
  • Posts: 14553
  • Country: fr
Re: Pointer confusion in C -language
« Reply #143 on: June 29, 2021, 05:54:42 pm »

Quote from: DiTBho
In C there are no "objects".

In C, an "object" is defined as "region of data storage in the execution environment, the contents of which can represent values"

Yes absolutely. It's a common "trap" to think of "objects" in a purely object-oriented manner (so with all the baggage, methods, etc.)
Actually, it's the "oriented" in the "object-oriented" term that further defines a language in which objects can define their own behavior, as opposed to languages in which functions/procedures operate on objects but are not "bound" to them.

In non-object-oriented languages, it's relatively common to use the term "object" to refer to what you quoted above. What other generic term to describe this would you use anyway?
 

Offline gf

  • Super Contributor
  • ***
  • Posts: 1245
  • Country: de
Re: Pointer confusion in C -language
« Reply #144 on: June 29, 2021, 06:29:16 pm »
Of course an array identifier can't be an l-value, just like a constant pointer.

It is still an lvalue, but in the context of most (but not all) expressions it is implicitly converted to a (non-lvalue) pointer to the first element.
https://en.cppreference.com/w/c/language/array, section "Array to pointer conversion"
 

Offline PlainName

  • Super Contributor
  • ***
  • Posts: 6871
  • Country: va
Re: Pointer confusion in C -language
« Reply #145 on: June 29, 2021, 06:35:39 pm »
Quote
Do you actually know what a compiler emits for array access? How is that different from pointers (except for the few points I mentioned)?

How is that relevant to C?

Or C++? Or, indeed, anything at all.
 

Offline TheCalligrapher

  • Regular Contributor
  • *
  • Posts: 151
  • Country: us
Re: Pointer confusion in C -language
« Reply #146 on: June 30, 2021, 05:48:13 pm »
Not sure what all this pile of crap means.

This "pile of crap" is known as a C programming language. It often triggers an emotional reaction from people who fail to understand its concepts, and principles it is built upon. The latter are quite simple, so I attribute that lack of understanding to the lack of effort, aka laziness.

A lot of words, but I haven't seen any concrete argument that would actually make my few above points "false".

The "words" are actually contained in the language specification, known as C standard. Moreover, the amount of effort spend by language enthusiasts on explaining that peculiar matter of arrays and pointers in enormous. I don't see any reason to copy-paste all that here for umpteenth time.

My intent is to point out your errors. And I did that with my signature surgical precision. The subsequent research is left entirely to you. I can only give you direction.

Like, a pointer for array access 'an imaginary concept"?

It is something that exists only in the mind of "C abstract machine". It only exist in paper documents, in formal definitions of various language features that rely on implicit array-to-pointer conversion (e.g. `[]` operator).

It has no reason to exist in the semantics of an actual real-life C implementation. And it doesn't.

Do you actually know what a compiler emits for array access?

Oh, yes, very well.

How is that different from pointers (except for the few points I mentioned)?

Um... You are diverging into some unrelated area here. At the machine language level all accesses to memory are performed through "pointers". From that point of view every lvalue in C can be though of as "pointer". Every time you access a variable in memory, it will go through some sort of "pointer". So, from that point of view you can ask the same question ("How is that different from pointers") about the entire object model of C language.

Sorry, dear. The machine-level concepts and your "how is that different from pointers" have no bearing on the C language concepts. You are trying to mix two different C language concepts: a concept of lvalue and a concept of pointer. In C these are not the same.

And as I said, except for exotic compiler extensions, the compiled code for accessing an array is no different from doing this directly with a pointer.

That is false. The compiled code for accessing an immediate array will be very different from the compiled code for accessing a pointed-to array through a pointer.

Moreover, compiled code for accessing an immediate struct object is the same as compiled code for accessing an immediate array. And compiled code for accessing a struct object through a pointer is the same as compiled code for accessing an array through a pointer.

Array objects are no different from struct objects. (Referring to commonly applicable operations, of course. You can't index-access a struct in C). Yet, you don't claim that struct are also "pointers", do you?

You can of course assign arrays to pointers for accessing them, and it makes no difference either.

It makes no difference cosmetically: the code looks the same. But it makes huge difference semantically and at the level of generated code. As I said above, accessing an immediate array and accessing an array through a pointer will generate completely different code.

The difference will become much more obvious when we start considering multi-dimensinal arrays. In fact, many people trapped in that misguided belief that "arrays are no different from pointers", get their first rude-awakening-style experience when they start working with multi-dimensinal arrays.

For example

Code: [Select]
int a[2][2] = { 0 };
int *const b[2] = { (int [2]) { 0 }, (int [2]) { 0 } };

a[0][0] = 42;
b[0][0] = 42;

In this little example above we have two different implementations of two-dimensional arrays `a` and `b`. One is a "classic" built-in 2D array. Another is a hand-made pointer-based "jagged" array. In other to build the latter we "assign arrays to pointers", as you said above. Yet, even though array access looks the same for both arrays (i.e. we just use `[k][m]` with both) this is purely a superficial similarity. The semantics of these two data structures are completely different and completely incompatible.

Or possibly you're being overly pedantic to the point of expressing worthless points that can only confuse people instead or helping them.

I'm a better judge of what helps people better in this matter.

To make things very clear, I'm strictly talking about C here. C++ is completely different.

When it comes to the matter of raw built-in arrays? No, C++ is not different at all, as long as we are talking about meaningfully comparable semantics.

In C++ you can even overload the [] operator, so that's a completely different territory.

No, you can't overload `[]` operator for a built-in type. So, I don't see why you are even mentioning it here. No need to bring C++ into the picture.

Arrays in C are just effectively allocated memory buffers, whether statically or on the stack.

All objects in C are just memory buffers (see my reference to structs above, for a specific example), with the exception of bit-fields. So, I don't see what point you are trying to make by this.

Yes, array `T [N]` in C is just a contiguous block of memory of size `N * sizeof(T)`. That's all. No pointers here.

Accessing an array in my world (maybe yours is in a different elevated sphere) means: accessing data within it. Which works exactly the same as with any other memory buffer.

I agree. And as I said above, accessing an immediate array is no different from accessing an immediate struct object. Yet, this is no reason to claim that struct objects are "just pointers".

Of course an array identifier can't be an l-value, just like a constant pointer. Just like functions.

Um... What??? This is patently false.

Arrays in C are lvalues. Just like constant pointers are lvalues

Code: [Select]
const int *a = 0; /* `a` is an lvalue */
int b[100]; /* `b` is an lvalue */

It is possible to create a non-lvalue array in C, but that would require some deliberate jumping through some hoops.

So, what are you talking about?

(Functions in C are not lvalues though - you got that right)
« Last Edit: June 30, 2021, 06:06:28 pm by TheCalligrapher »
 

Online SiliconWizard

  • Super Contributor
  • ***
  • Posts: 14553
  • Country: fr
Re: Pointer confusion in C -language
« Reply #147 on: June 30, 2021, 06:43:22 pm »
Of course an array identifier can't be an l-value, just like a constant pointer.

It is still an lvalue, but in the context of most (but not all) expressions it is implicitly converted to a (non-lvalue) pointer to the first element.
https://en.cppreference.com/w/c/language/array, section "Array to pointer conversion"

You can't assign anything to an array identifier, which is exactly what I meant.
I'm not sure if we are talking about the same thing or whatever else.

If you convert an array identifier to some other type, obviously you can do weird stuff with it. But you still can't modify the *value* of the idenfitier itself. It will still refer to the same area in memory.
Again, just like a declared function.

like if you declare:
int array[10];
there is no way you can do: array = xxx; at any point. Which is the same as with const pointers, which I mentioned. And, do not confuse const pointers with pointers to const... (which can be confusing syntax-wise in C, btw.)

Just like if you declare a function:
int foo() { ... }
there is no away you can do: foo = xxx; at any point.

If you assign an array identifier to a pointer, then obviously the pointer can be anything as long as the conversion is legit and/or you use a proper cast.

I don't get why you'd mention array to pointer conversion to reply to my statement. An array identifier itself can't be used as an l-value. If you convert it to anything else, then it's not an array identifier anymore. That's all I meant.

Like what I've read above, it looks like a couple of you confuse "arrays" with accessing their content. I can't see how a C "array" itself could ever be an l-value, if by "array" you consider the array identifier itself, and not expressions accessing its contents.
« Last Edit: June 30, 2021, 07:01:37 pm by SiliconWizard »
 

Offline TheCalligrapher

  • Regular Contributor
  • *
  • Posts: 151
  • Country: us
Re: Pointer confusion in C -language
« Reply #148 on: June 30, 2021, 07:04:51 pm »
You can't assign anything to an array identifier, which is exactly what I meant.

If that's what you meant, then you certainly expressed yourself rather... ambiguously. The property of being (or not being) and lvalue has nothing to do with the ability (or inability) to serve as the recipient side of an assignment.

If you convert an array identifier to some other type, obviously you can do weird stuff with it. But you still can't modify the *value* of the idenfitier itself. It will still refer to the same area in memory.

Of course. Every (!) object, every variable in C is permanently attached to a specific location in memory for its entire lifetime. You can't "move" to another location in memory. It is just how language-wide object model in C is defined. No reason to bring it up in the context of arrays. Arrays are in no way special in that regard.

I don't get why you'd mention array to pointer conversion to reply to my statement. An array identifier itself can't be used as an l-value.

You are abusing the terminology again. In C language the property of "being an lvalue" is approximately equivalent to "data that can serve as a valid argument for unary &". (This is not a strict equivalence, but a still a fairly precise rule of thumb). If a piece of data has a location in memory, then it is an lvalue

Code: [Select]
int a[10];
&a; /* a valid expression, which immediately proves that an array is an lvalue */

This is why the term "lvalue" is often expanded as "location value". Yes, we all know how this term was originally coined, but the truth is that its anecdotal origin never had any relation to its actual meaning. So, why are you trying to use that term in a meaning it never had is not clear to me. And you are the one who accused me of confusing people...

Just like if you declare a function:
int foo() { ... }
there is no away you can do: foo = xxx; at any point.

As a side note: the decision to consider (or not) functions as lvalues is a purely administrative one, a matter of decree. You can decree it either way. E.g. in C++ functions are considered lvalues, even though in C++ you can't assign anything to a function either.
« Last Edit: June 30, 2021, 07:14:18 pm by TheCalligrapher »
 

Offline Nominal Animal

  • Super Contributor
  • ***
  • Posts: 6321
  • Country: fi
    • My home page and email address
Re: Pointer confusion in C -language
« Reply #149 on: June 30, 2021, 07:49:40 pm »
Not directed at anyone in particular, intended to be read as a help guide or study point:

Consider the value of the C expression
    (buffer == (char *)(&buffer))
given
    char buffer[1];

If you do not believe the expression is a compile-time constant with value 1 –– remember, this is C and not C++ ––, your belief is incorrect.  I suggest revision and practical experimentation to fix.

If you have problems seeing how the expression is a constant with value 1, your understanding of C is incomplete.  I suggest further study.

If you don't have the terminology to put in a single paragraph with two or three sentences exactly why the expression is a constant with value 1, your terminology is incorrect or incomplete.  I suggest redefining the terms and idioms you use internally to describe C structures and rules, until you can.

If you think you need to consult the C standard to prove why the above is not a constant with value 1, I recommend switching to a different programming language, or perhaps another career.  The purpose of the C standard is to describe existing behaviour developers should be able to rely on, according to the very cover sheet of the standard.  Proving why existing, intuitive, correctly working as expected code should not work because of an esoteric strict reading of the standard, has nothing to do with programming, and everything to do with linguistics (of human language) and language-lawyerism.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf