473,657 Members | 2,661 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Contrived casting situation

The thread where casting is being discussed motivated me to try this. Let's
say you wanted to populate a BankRecord structure (as I defined below) with
17-character record numbers, but with the record numbers separated into a SSN
and an account number (and with a terminating '\0')...

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
char SSN[9];
char AccountNum[8];
char end;
} BankRecord;

int main( int argc, char * argv[] )
{
int i;
BankRecord *a;

if( argc < 2 ) {
printf( "No information provided\n" );
return EXIT_FAILURE;
}
if( (a=malloc((argc-1)*(sizeof(Bank Record)))) == NULL ) {
printf( "Malloc() failed\n" );
return EXIT_FAILURE;
}
for( i=1; i < argc; i++ ) {
snprintf( (char*)&a[i-1], sizeof(BankReco rd), "%s", argv[i] );
}
for( i=0; i < argc-1; i++ ) {
printf( "%s\n", (char*)&a[i] ); /* just to prove that it works */
}
return EXIT_SUCCESS;
}

1) Is this code legal C? (it compiled with no warnings for me and worked
correctly)
2) Is the cast of a structure to a char* the best way to solve this contrived
problem?
3) How can I declare BankRecord in such a way so that end is a const char
equal to '\0'? Would that be desirable?
4) Any other comments?

--
Christopher Benson-Manica | Jumonji giri, for honour.
ataru(at)cybers pace.org |
Nov 13 '05 #1
13 1928
Christopher Benson-Manica wrote:

The thread where casting is being discussed motivated me to try this. Let's
say you wanted to populate a BankRecord structure (as I defined below) with
17-character record numbers, but with the record numbers separated into a SSN
and an account number (and with a terminating '\0')...

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
char SSN[9];
char AccountNum[8];
char end;
} BankRecord;

int main( int argc, char * argv[] )
{
int i;
BankRecord *a;

if( argc < 2 ) {
printf( "No information provided\n" );
return EXIT_FAILURE;
}
if( (a=malloc((argc-1)*(sizeof(Bank Record)))) == NULL ) {
printf( "Malloc() failed\n" );
return EXIT_FAILURE;
}
for( i=1; i < argc; i++ ) {
snprintf( (char*)&a[i-1], sizeof(BankReco rd), "%s", argv[i] );
}
for( i=0; i < argc-1; i++ ) {
printf( "%s\n", (char*)&a[i] ); /* just to prove that it works */
}
return EXIT_SUCCESS;
}

1) Is this code legal C? (it compiled with no warnings for me and worked
correctly)
The code is "legal" in the sense that it exhibits no
undefined behavior (unless I've missed something). However,
it is not strictly conforming because it has implementation-
defined behavior: sizeof(BankReco rd) is at least 18, but
might be larger because of padding within the struct. Thus,
the program's output when given a 20-character command-line
argument, say, depends on the details of the implementation.

In short: It is not guaranteed that the ninth input
character lands in the AccountNum[0] spot; it might instead
land in the limbo between SSN and AccountNum. The code
works, but might not be doing what you want.
2) Is the cast of a structure to a char* the best way to solve this contrived
problem?
No, because it invokes the implementation-defined behavior
mentioned above and is thus not portable.
3) How can I declare BankRecord in such a way so that end is a const char
equal to '\0'? Would that be desirable?
There's no way to achieve this with a declaration. Whether
that's a desirable state of affairs is a matter of taste -- if
you want C++ and constructors, you know where to find them.
4) Any other comments?


Yes: Write what you mean, not something else that you sort
of think might produce the same effect. If you've got two
distinct values -- SSN and AccountNum -- treat them as such.
If you want to view them as sub-fields of a single larger
string, declare a single 18-element array to contain that
single larger string.

A guess: Did you cut your teeth on FORTRAN, and perhaps
become overly fond of the EQUIVALENCE declaration? If so,
my recommendation is to lose that habit when writing C.

--
Er*********@sun .com
Nov 13 '05 #2
Christopher Benson-Manica wrote:
The thread where casting is being discussed motivated me to try this. Let's
say you wanted to populate a BankRecord structure (as I defined below) with
17-character record numbers, but with the record numbers separated into a SSN
and an account number (and with a terminating '\0')...

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
char SSN[9];
char AccountNum[8];
char end;
} BankRecord;

int main( int argc, char * argv[] )
{
int i;
BankRecord *a;

if( argc < 2 ) {
printf( "No information provided\n" );
return EXIT_FAILURE;
}
if( (a=malloc((argc-1)*(sizeof(Bank Record)))) == NULL ) {
printf( "Malloc() failed\n" );
return EXIT_FAILURE;
}
for( i=1; i < argc; i++ ) {
snprintf( (char*)&a[i-1], sizeof(BankReco rd), "%s", argv[i] );
}
for( i=0; i < argc-1; i++ ) {
printf( "%s\n", (char*)&a[i] ); /* just to prove that it works */
}
return EXIT_SUCCESS;
}

1) Is this code legal C? (it compiled with no warnings for me and worked
correctly)
Yep.
2) Is the cast of a structure to a char* the best way to solve this contrived
problem?
You could use a union, but I don't think that would be better.
3) How can I declare BankRecord in such a way so that end is a const char
equal to '\0'? Would that be desirable?
You can't. It would be desirable in a way, but I think it would create
a lot of complexities in the language that would quickly defeat its
desirability.
4) Any other comments?


I think if the argument passed is too long, the a[i-1] in the snprintf
call will end up null-less. I think maybe sscanf would be better because
you can specify the length in the format specifier and it will append a
null even if the entire length is used. Other than that I think its a
valid piece of code.

Matt Gregory

Nov 13 '05 #3


Christopher Benson-Manica wrote:
The thread where casting is being discussed motivated me to try this. Let's
say you wanted to populate a BankRecord structure (as I defined below) with
17-character record numbers, but with the record numbers separated into a SSN
and an account number (and with a terminating '\0')...

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
char SSN[9];
char AccountNum[8];
char end;
} BankRecord;

int main( int argc, char * argv[] )
{
int i;
BankRecord *a;

if( argc < 2 ) {
printf( "No information provided\n" );
return EXIT_FAILURE;
}
if( (a=malloc((argc-1)*(sizeof(Bank Record)))) == NULL ) {
printf( "Malloc() failed\n" );
return EXIT_FAILURE;
}
for( i=1; i < argc; i++ ) {
snprintf( (char*)&a[i-1], sizeof(BankReco rd), "%s", argv[i] );
}
for( i=0; i < argc-1; i++ ) {
printf( "%s\n", (char*)&a[i] ); /* just to prove that it works */
You should try another test:
printf("Account Num = %s\n",a[i].Accountum);
and see if it still works as expected.
}
return EXIT_SUCCESS;
}

1) Is this code legal C? (it compiled with no warnings for me and worked
correctly)
2) Is the cast of a structure to a char* the best way to solve this contrived
problem?


No, You have issues of struct member padding which are address in
fag questions 2.13 and 2.12

http://www.eskimo.com/~scs/C-faq/q2.13.html
http://www.eskimo.com/~scs/C-faq/q2.12.html

--
Al Bowers
Tampa, Fl USA
mailto: xa*@abowers.com base.com (remove the x)
http://www.geocities.com/abowers822/

Nov 13 '05 #4
Eric Sosman wrote:

Christopher Benson-Manica wrote:

[...]
typedef struct {
char SSN[9];
char AccountNum[8];
char end;
} BankRecord;

[...]

In short: It is not guaranteed that the ninth input
character lands in the AccountNum[0] spot; it might instead
land in the limbo between SSN and AccountNum.


Um, er, "Oops." The ninth input character necessarily
lands in SSN[8]; it's the *tenth* character whose location
is uncertain. Sorry about that.

--
Er*********@sun .com
Nov 13 '05 #5
Matt Gregory <ms********@ear thlink.net> spoke thus:
You can't. It would be desirable in a way, but I think it would create
a lot of complexities in the language that would quickly defeat its
desirability.
Just making sure, thanks :)
I think if the argument passed is too long, the a[i-1] in the snprintf
call will end up null-less. I think maybe sscanf would be better because
you can specify the length in the format specifier and it will append a
null even if the entire length is used. Other than that I think its a
valid piece of code.


According to my documentation for snprintf(), it writes size-1 characters and
the size-th character is guaranteed to be '\0', so if sizeof(BankReco rd) is
18, I'm fine. Of course, as the previous reply noted, that isn't guaranteed
to be the case...

--
Christopher Benson-Manica | Jumonji giri, for honour.
ataru(at)cybers pace.org |
Nov 13 '05 #6
Eric Sosman <Er*********@su n.com> spoke thus:
Um, er, "Oops." The ninth input character necessarily
lands in SSN[8]; it's the *tenth* character whose location
is uncertain. Sorry about that.


So structure fields are not guaranteed to be contiguous? How unfortunate :(

--
Christopher Benson-Manica | Jumonji giri, for honour.
ataru(at)cybers pace.org |
Nov 13 '05 #7
Christopher Benson-Manica <at***@nospam.c yberspace.org> scribbled the following:
Eric Sosman <Er*********@su n.com> spoke thus:
Um, er, "Oops." The ninth input character necessarily
lands in SSN[8]; it's the *tenth* character whose location
is uncertain. Sorry about that.
So structure fields are not guaranteed to be contiguous? How unfortunate :(


No, they aren't. The implementation is free to add any padding it likes
between any two members, or after the last member. The first member
MUST begin at offset 0, though.

--
/-- Joona Palaste (pa*****@cc.hel sinki.fi) ---------------------------\
| Kingpriest of "The Flying Lemon Tree" G++ FR FW+ M- #108 D+ ADA N+++|
| http://www.helsinki.fi/~palaste W++ B OP+ |
\----------------------------------------- Finland rules! ------------/
"That's no raisin - it's an ALIEN!"
- Tourist in MTV's Oddities
Nov 13 '05 #8
Eric Sosman wrote:
Christopher Benson-Manica wrote:
1) Is this code legal C? (it compiled with no warnings for me and worked
correctly)

The code is "legal" in the sense that it exhibits no
undefined behavior (unless I've missed something). However,
it is not strictly conforming because it has implementation-
defined behavior: sizeof(BankReco rd) is at least 18, but
might be larger because of padding within the struct. Thus,
the program's output when given a 20-character command-line
argument, say, depends on the details of the implementation.


Oh, I forgot about that. Oops. This is the very thing that
drove me nuts the first time I tried to translate a Pascal
program to C which wrote records to disk by calling Write().
Damn. Never did get that debugged. Had to switch back to
Pascal.

Matt Gregory

Nov 13 '05 #9
Joona I Palaste wrote:

Christopher Benson-Manica <at***@nospam.c yberspace.org> scribbled the following:
Eric Sosman <Er*********@su n.com> spoke thus:
Um, er, "Oops." The ninth input character necessarily
lands in SSN[8]; it's the *tenth* character whose location
is uncertain. Sorry about that.

So structure fields are not guaranteed to be contiguous? How unfortunate :(


No, they aren't. The implementation is free to add any padding it likes
between any two members, or after the last member. The first member
MUST begin at offset 0, though.

The case for padding in structures is for alignment of multibyte
objects, int, long, double, etc. The char is a single-byte object. It
can appear anywhere and has no known alignment requirements, even as an
array. There need be no padding between char objects. I betcha... sizeof
(BankRecord) == 18 on every implementation we have.
--
Joe Wright mailto:jo****** **@earthlink.ne t
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---
Nov 13 '05 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

231
23107
by: Brian Blais | last post by:
Hello, I saw on a couple of recent posts people saying that casting the return value of malloc is bad, like: d=(double *) malloc(50*sizeof(double)); why is this bad? I had always thought (perhaps mistakenly) that the purpose of a void pointer was to cast into a legitimate date type. Is this wrong? Why, and what is considered to be correct form?
19
1742
by: Ramesh Tharma | last post by:
Hi, Is any one knows what's wrong with the following code, I was told that it will compile and run but it will crash for some values. Assume that variables are initilized. char* c; long* lg;
4
1690
by: c | last post by:
Hello All, I am struggling with simple casting issue within c# and would really appreciate some insight into where I am going wrong. I have two classes, ClassA and ClassB. Each implements a "public static implicit operator" to allow silent casting from one to the other. This works fine, per the documents I have read. However, I am unable to do this:
33
3642
by: Mark P | last post by:
A colleague asked me something along the lines of the following today. For some type X he has: X* px = new X; Then he wants to convert px to a char* (I'm guessing for the purpose of serializing the object array). I can think of three ways to do this:
5
5922
by: brekehan | last post by:
I've always been a little sketchy on the differences between static, dynamic, and reinterpret casting. I am looking to clean up the following block by using C++ casting instead of the C style casting. from what I am reading, I should use reinterpret cast in this situation, is that correct? Why does static and dynamic casting fail me? // please excuse the windows types, it is necessary in this code, // but the question remains C++ related
5
2719
by: johanatan | last post by:
Does anyone know the reasons for the lack of an implicit casting operator in any greater depth than: A. Automatic conversion is believed to be too error prone. (from the FAQ at the bottom of: http://www.boost.org/libs/smart_ptr/shared_ptr.htm) Can anyone say specifically what about the implicit conversion would be dangerous? I can think of a few things that would require care about usage of smart pointers with implicit conversions,...
9
3458
by: Taras_96 | last post by:
Hi everyone, I was experimenting with static_cast and reinterpret cast #include <iostream> struct A1 { int a; }; struct A2 { double d; }; struct B : public A1, A2
5
3894
by: jason.cipriani | last post by:
There have been some recent threads about casting pointers to and from void* that have me rethinking some of my usual practices. I have a couple of questions. 1. What is the purpose of C++'s static_cast<>? In other words, is there any real difference between statements like (with non-pointer types): double a = 3.4; int b = (int)a; // <--- this
19
1940
by: =?Utf-8?B?WWFua2VlIEltcGVyaWFsaXN0IERvZw==?= | last post by:
I'm doing my c# more and more like i used to code c++, meaning i'm casting more often than creating an instance of objects. like : protected void gvOrderDetailsRowDataBound(object sender, GridViewRowEventArgs e) { if (e.Row.RowType == DataControlRowType.DataRow) { switch (((Sale)e.Row.DataItem).SzPN) {
0
8407
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
8319
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,...
0
8837
Oralloy
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...
0
8739
jinu1996
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...
1
8512
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
7347
agi2029
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...
1
6175
isladogs
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...
0
5638
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();...
1
2739
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 using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.