Dear experts,
according to my interpretation of the Standard, loop 1 in the
following program is legal, while loop 2 is not (see explanation
below). This looks a bit counterintuitiv e, though; do you know
the truth?
Thanks a lot in advance,
Bernd Gaertner.
#include<iostre am>
int main()
{
int a[2][3] = { {0, 1, 2}, {3, 4, 5} };
int* first = a[0]; // pointer to a[0][0]
// loop 1
for (int* p = first; p < first+6; ++p)
std::cout << *p; // 012345
// loop 2
for (int* p = first; p < first+6; p+=2)
std::cout << *p; // 024
return 0;
}
Explanation: [decl.array] 7-9 implies that the memory layout of
"int a[3][2]" is as for "int a[6]" - the six ints are consecutive
in memory. This means that during any iteration of loop 1, both p
and ++p are pointers to elements (or past-the-end pointers) of the
*same* three-element array, namely either a[0] or a[1]. In this
case, [expr.add] 5 guarantees well-defined behavior. In loop 2,
if p == first+2 (pointer to last element of a[0]), p+=2 points to
the second element of a[1], so p and p+=2 do not refer to the same
array. In this case, [expr.add] 5 stipulates undefined behavior. 4 4384
On Nov 12, 1:58 pm, Bernd Gaertner <gaert...@inf.e thz.chwrote:
according to my interpretation of the Standard, loop 1 in the
following program is legal, while loop 2 is not (see explanation
below). This looks a bit counterintuitiv e, though; do you know
the truth?
Neither are legal, although both are likely to work on most
implementations .
#include<iostre am>
int main()
{
int a[2][3] = { {0, 1, 2}, {3, 4, 5} };
int* first = a[0]; // pointer to a[0][0]
More precisely: a pointer to the first element in a[0]. More
precisely, a pointer to an int which is the first element of an
array of 3 ints. Legal values for this pointer a thus first,
first+1, first+2 and first+3; the last may not be dereferenced.
In practice, the only time this will fail is with a bounds
checking implementation using fat pointers. (CenterLine once
sold such a compiler; I don't know what the current status is,
but ICS is still selling a compiler under the CenterLine mark.)
// loop 1
for (int* p = first; p < first+6; ++p)
std::cout << *p; // 012345
// loop 2
for (int* p = first; p < first+6; p+=2)
std::cout << *p; // 024
return 0;
}
Explanation: [decl.array] 7-9 implies that the memory layout of
"int a[3][2]" is as for "int a[6]" - the six ints are consecutive
in memory.
Yes, but it's not too clear what you can do with that. The
standard has been very carefully worded to allow compiler bounds
checking (even if no one, or almost no one, does it). When you
assign a[0] to first, the bounds are a[0][0]...a[0][3]. A
compiler is allowed to maintain this information with the
pointer (i.e. a fat pointer), and check it each time you modify
the pointer.
This means that during any iteration of loop 1, both p
and ++p are pointers to elements (or past-the-end pointers) of the
*same* three-element array, namely either a[0] or a[1]. In this
case, [expr.add] 5 guarantees well-defined behavior. In loop 2,
if p == first+2 (pointer to last element of a[0]), p+=2 points to
the second element of a[1], so p and p+=2 do not refer to the same
array. In this case, [expr.add] 5 stipulates undefined behavior.
That's a different problem. Obviously, a bounds checking
implementation would fail here; supposedly, at least, there have
also been cases where it would fail in special cases without
bounds checking. (I don't think it would ever fail without
bounds checking for an on stack array of small elements like
int. It might fail if the array were dynamically allocated,
however, or if the elements were significantly larger---things
that could cause the pointer to point to memory that didn't
exist or that wasn't mapped.)
--
James Kanze (GABI Software) email:ja******* **@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientier ter Datenverarbeitu ng
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Thanks a lot, for your answer, Alf! There are some things I still don't
understand, though (and yes, it's homework-related, but not my homework
but that of my students).
Alf P. Steinbach wrote:
>#include<iostr eam>
int main() { int a[2][3] = { {0, 1, 2}, {3, 4, 5} }; int* first = a[0]; // pointer to a[0][0]
// loop 1 for (int* p = first; p < first+6; ++p) std::cout << *p; // 012345
// loop 2 for (int* p = first; p < first+6; p+=2) std::cout << *p; // 024
return 0; }
You have no guarantee that a pointer to the first array element can be
treated as a pointer to the array. On a segmented architecture the
pointers might theoretically (although not in practice) be completely
different beast, and the two inner arrays might reside in different
segments, "you can't get there from here".
This seems to be in contradiction to [dcl.array] 1 where it is stated
that "An object of array type contains a contiguously allocated nonempty
subset of N subobjects of type T". And a twodimensional array is simply
an array where T is another array type.
>In loop 2, if p == first+2 (pointer to last element of a[0]), p+=2 points to the second element of a[1], so p and p+=2 do not refer to the same array. In this case, [expr.add] 5 stipulates undefined behavior.
The reasoning here seems to not be meaningful in any way, but the
conclusion is just about right.
The reasoning was based on the assumed fact that the two subarrays are
contiguoulsy allocated in memory.
On the suspicion that this is HOMEWORK, I'll leave it as an exercise to
figure out why the second loop has formally Undefined Behavior in
addition to the UB considerations that apply to the first loop.
I figured one thing out that also applies to loop 1 (stupid me): the
behavior of the operation "first+6" is already undefined since first and
the result first+6 definitely do not point to elements (or past the end)
of the same array. But what if we loop as follows?
// loop 1
int* p = first;
for (int i=0; i<6; ++i)
std::cout << *p++; // 012345
Bernd Gaertner wrote:
Thanks a lot, for your answer, Alf! There are some things I still don't
understand, though (and yes, it's homework-related, but not my homework
but that of my students).
Alf P. Steinbach wrote:
>>#include<iost ream>
int main() { int a[2][3] = { {0, 1, 2}, {3, 4, 5} }; int* first = a[0]; // pointer to a[0][0]
// loop 1 for (int* p = first; p < first+6; ++p) std::cout << *p; // 012345
// loop 2 for (int* p = first; p < first+6; p+=2) std::cout << *p; // 024
return 0; }
>You have no guarantee that a pointer to the first array element can be treated as a pointer to the array. On a segmented architecture the pointers might theoretically (although not in practice) be completely different beast, and the two inner arrays might reside in different segments, "you can't get there from here".
This seems to be in contradiction to [dcl.array] 1 where it is stated
that "An object of array type contains a contiguously allocated nonempty
subset of N subobjects of type T". And a twodimensional array is simply
an array where T is another array type.
That only concerns the layout of the arrays in memory. It does not concern
what you can do with pointer arithmetic. The standard does not preclude an
implementation to perform bounds checking. In particular, an implementation
is allowed to use decorated pointers that keep track of the range of
validity for pointer arithmetic through extra data not used in
dereferencing. Although this may not correspond to the intuitive notion of
a pointer, it is a perfectly valid implementation. The compiler would
deduce such ranges of validity from type information. In the above cases,
range checking would find an access violation once you increment p past the
bound of the 1D-array used to initialize it.
[snip]
Best
Kai-Uwe Bux
Thanks for all your in-depth answers! I understand the issue much better
now, and in retrospect it was somewhat naive to expect defined behavior
for the loops in my original posting.
Best regards,
Bernd. This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics |
by: ceo |
last post by:
Hi,
Following is a program that doesn't give the expected output, not sure
what's wrong here. I'm adding the size of derived class to the base
class pointer to access the next element in the array. Why does bp
point to some address that is not &d?
Please clarify.
Thanks,
|
by: Alex Fraser |
last post by:
From searching Google Groups, I understand that void pointer arithmetic is a
constraint violation, which is understandable. However, generic functions
like qsort() and bsearch() must in essence do exactly this, and similarly
generic functions seem to have useful applications.
In a few posts I read, it was suggested to avoid void pointer arithmetic by
casting to a char pointer, and performing arithmetic on that (in multiples
of...
|
by: Francois Grieu |
last post by:
Are these programs correct ?
#include <stdio.h>
unsigned char a = {1,2};
int main(void) {
unsigned char j;
for(j=1; j<=2; ++j)
printf("%u\n", *( a+j-1 ));
return 0; }
|
by: randomtalk |
last post by:
hello everyone!
Well, recently i've been trying to pick up c and see what is pointer
all about (been programming in lisp/python for the better part of my
last two years)..
mmm.. I'm currently reading The C Programming Language Second Edition..
When i hit on pointer arithmetic example, i have no idea what's
happening, hopefully some of you could alleviate my confusion, so here
goes:
|
by: Erik de Castro Lopo |
last post by:
Hi all,
The GNU C compiler allows a void pointer to be incremented and
the behaviour is equivalent to incrementing a char pointer.
Is this legal C99 or is this a GNU C extention?
Thanks in advance.
Erik
| |
by: barikat |
last post by:
int a;
int *Ptr1, *Ptr2;
Ptr1 = a;
Ptr1++;
Ptr2 = a;
printf("Ptr1 : %p\n", Ptr1);
printf("Ptr2 : %p\n\n", Ptr2);
|
by: Bill Reid |
last post by:
Bear with me, as I am not a "professional" programmer, but I was
working on part of program that reads parts of four text files into
a buffer which I re-allocate the size as I read each file. I read some
of the items from the bottom up of the buffer, and some from the
top down, moving the bottom items back to the new re-allocated
bottom on every file read.
Then when I've read all four files, I sort the top and bottom items
separately...
|
by: Summercool |
last post by:
Can we confirm the following? also someone said, Java also has
"reference" like in C++, which is an "implicit pointer":
Pointer and Reference
---------------------
I am starting to see what pointer and reference are and how they
relate
to each other.
|
by: =?Utf-8?B?RGlwZXNoX1NoYXJtYQ==?= |
last post by:
Hi all,
I am porting my code in VC++ to VC.net i.e managed. I have seen somewhere
that i need to convert my char* to String*, but String * doesnt perform
pointer arithmetic like String* p; *p++=' ';
So please suggest as to what i have to do? Am i doing wrong by converting
char* to String* in managed VC.net.
Thanks,
Dipesh.
|
by: =?iso-8859-1?b?VG9t4XMg0yBoyWlsaWRoZQ==?= |
last post by:
Coming originally from C++, I used to do the likes of the following,
using a pointer in a conditional:
void Func(int *p)
{
if (p)
{
*p++ = 7;
*p++ = 8;
|
by: Hystou |
last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it.
First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
| |
by: Oralloy |
last post by:
Hello folks,
I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>".
The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed.
This is as boiled down as I can make it.
Here is my compilation command:
g++-12 -std=c++20 -Wnarrowing bit_field.cpp
Here is the code in...
|
by: jinu1996 |
last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth.
The Art of Business Website Design
Your website is...
|
by: agi2029 |
last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own....
Now, this would greatly impact the work of software developers. The idea...
|
by: isladogs |
last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM).
In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules.
He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms.
Adolph will...
|
by: conductexam |
last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one.
At the time of converting from word file to html my equations which are in the word document file was convert into image.
Globals.ThisAddIn.Application.ActiveDocument.Select();...
|
by: TSSRALBI |
last post by:
Hello
I'm a network technician in training and I need your help.
I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs.
The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols.
I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
| |
by: 6302768590 |
last post by:
Hai team
i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
|
by: bsmnconsultancy |
last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...
| |