init array with instance - C
This is a discussion on init array with instance - C ; Hello there,
I want to init my Test-Object with an initial value, but it doesn't work.
What's wrong or how can it be done?
#import <objc/Object.h>
@interface Test: Object
{
int L;
int array[L];
}
-(Test *) initWith: (int) i;
...
-
init array with instance
Hello there,
I want to init my Test-Object with an initial value, but it doesn't work.
What's wrong or how can it be done?
#import <objc/Object.h>
@interface Test: Object
{
int L;
int array[L];
}
-(Test *) initWith: (int) i;
@end
@implementation Test;
-(Test *) initWith: (int) i
{
L = i;
self = [super init];
return self;
}
@end
int main()
{
Test *objekt = [[Test alloc] initWith: 100];
return 0;
}
-
Re: init array with instance
In article <e78gvv$s85$1@online.de>,
Jonathan Groß <pge03cnx@studserv.uni-leipzig.de> wrote:
> I want to init my Test-Object with an initial value, but it doesn't work.
> What's wrong or how can it be done?
>
> -(Test *) initWith: (int) i
> {
> L = i;
>
> self = [super init];
> return self;
> }
>
the first line of the above function is shorthand for:
self->L = i;
so, it won't function correctly if it is before the next line.
The fix is to reorder the two lines:
self = [super init];
L = i;
-
Re: init array with instance
In article <e78gvv$s85$1@online.de>,
Jonathan Groß <pge03cnx@studserv.uni-leipzig.de> wrote:
>Hello there,
>
>I want to init my Test-Object with an initial value, but it doesn't work.
>What's wrong or how can it be done?
>
>#import <objc/Object.h>
>
>@interface Test: Object
>
>{
> int L;
> int array[L];
>}
if your goal is to allocate an array of 'L' elements, the above will not
work, as 'L' is not known at compile time.
You will need to alocate the array yourself. So, rather than declaring
'int array[L]' as an instance variable, you need to declare an instance
variable that is a suitable pointer, and then allocate a suitably large
block of memory and assign it to that pointer:
@interface Test : Object {
int L;
int *array;
}
>
>@end
>
>@implementation Test;
>
-(Test *) initWith: (int) i
{
if ((self = [super init]) != nil) {
L = i;
array = (int *)malloc(L * sizeof(int));
}
return self;
}
>@end
>
>int main()
>{
> Test *objekt = [[Test alloc] initWith: 100];
> return 0;
>}
Best wishes,
// Christian Brunschen
-
Re: init array with instance
On 20/6/06 16:30, Christian Brunschen wrote:
> In article <e78gvv$s85$1@online.de>,
> Jonathan Groß <pge03cnx@studserv.uni-leipzig.de> wrote:
>> Hello there,
>>
>> I want to init my Test-Object with an initial value, but it doesn't work.
>> What's wrong or how can it be done?
>>
>> #import <objc/Object.h>
>>
>> @interface Test: Object
>>
>> {
>> int L;
>> int array[L];
>> }
>
> if your goal is to allocate an array of 'L' elements, the above will not
> work, as 'L' is not known at compile time.
>
Out of pedantry, if the C in Objective-C is C99 then you *can* declare a
variable-length array. However, you still can't use L because the value
of L isn't known at +alloc time. ObjC probably shouldn't support
variable-length arrays anyway, even under ObjC99, because you
effectively break the ability to subclass if you do it. So your
solution which I removed was still the right one :-)
-
Re: init array with instance
Graham J Lee <uk.ac.ox.physics.teaching@leeg.invalid> wrote:
> On 20/6/06 16:30, Christian Brunschen wrote:
>> In article <e78gvv$s85$1@online.de>,
>> Jonathan Gro? <pge03cnx@studserv.uni-leipzig.de> wrote:
>>> Hello there,
>>>
>>> I want to init my Test-Object with an initial value, but it doesn't work.
>>> What's wrong or how can it be done?
>>>
>>> #import <objc/Object.h>
>>>
>>> @interface Test: Object
>>>
>>> {
>>> int L;
>>> int array[L];
>>> }
>>
>> if your goal is to allocate an array of 'L' elements, the above will not
>> work, as 'L' is not known at compile time.
>
> Out of pedantry, if the C in Objective-C is C99 then you *can* declare a
> variable-length array. However, you still can't use L because the value
> of L isn't known at +alloc time. ObjC probably shouldn't support
> variable-length arrays anyway, even under ObjC99, because you
> effectively break the ability to subclass if you do it. So your
> solution which I removed was still the right one :-)
C99 variable-length arrays only work for local variables, not for struct
(and therefore class) members. If you think about it, there are no
non-constant values that would work, because the size of types has to be
known at compile time, but the size of a particular variable doesn't.
Using malloc/free is definitely the right way to go in this case. I
recommend it even for local variables, because variable-length arrays use
horrible stack mojo which is prone to breaking when your size becomes "too
large". It's basically a friendly face around alloca(), and C programmers
who know about it usually have a healthy respect and fear for alloca().
--
Michael Ash
Rogue Amoeba Software
-
Re: init array with instance
On 2006-06-20 17:30:34 +0200, cb@festis.df.lth.se (Christian Brunschen) said:
> In article <e78gvv$s85$1@online.de>,
> Jonathan Groß <pge03cnx@studserv.uni-leipzig.de> wrote:
>> Hello there,
>>
>> I want to init my Test-Object with an initial value, but it doesn't work.
>> What's wrong or how can it be done?
>>
>> #import <objc/Object.h>
>>
>> @interface Test: Object
>>
>> {
>> int L;
>> int array[L];
>> }
>
> if your goal is to allocate an array of 'L' elements, the above will
> not work, as 'L' is not known at compile time.
>
>
> @interface Test : Object {
> int L;
> int *array;
> }
> -(Test *) initWith: (int) i
> {
> if ((self = [super init]) != nil) {
> L = i;
> array = (int *)malloc(L * sizeof(int));
> }
> return self;
> }
Thanks. This did work!
-
Re: init array with instance
On 20/6/06 20:01, Michael Ash wrote:
> Graham J Lee <uk.ac.ox.physics.teaching@leeg.invalid> wrote:
>> On 20/6/06 16:30, Christian Brunschen wrote:
>>> In article <e78gvv$s85$1@online.de>,
>>> Jonathan Gro? <pge03cnx@studserv.uni-leipzig.de> wrote:
>>>> Hello there,
>>>>
>>>> I want to init my Test-Object with an initial value, but it doesn't work.
>>>> What's wrong or how can it be done?
>>>>
>>>> #import <objc/Object.h>
>>>>
>>>> @interface Test: Object
>>>>
>>>> {
>>>> int L;
>>>> int array[L];
>>>> }
>>> if your goal is to allocate an array of 'L' elements, the above will not
>>> work, as 'L' is not known at compile time.
>> Out of pedantry, if the C in Objective-C is C99 then you *can* declare a
>> variable-length array. However, you still can't use L because the value
>> of L isn't known at +alloc time. ObjC probably shouldn't support
>> variable-length arrays anyway, even under ObjC99, because you
>> effectively break the ability to subclass if you do it. So your
>> solution which I removed was still the right one :-)
>
> C99 variable-length arrays only work for local variables, not for struct
> (and therefore class) members. If you think about it, there are no
> non-constant values that would work, because the size of types has to be
> known at compile time, but the size of a particular variable doesn't.
Yup, you're right about C99, and I was wrong and misleading. I was
thinking of flexible arrays, which GNU C (at least) supports as long as
they're the last element of the struct (effectively by malloc()ing past
the end of the struct). ObjC *doesn't* allow them, because it would be
a right mess trying to deal with that and subclassing would effectively
become impossible.
-
Re: init array with instance
Jonathan Groß wrote:
> On 2006-06-20 17:30:34 +0200, cb@festis.df.lth.se (Christian Brunschen)
> said:
>
>> In article <e78gvv$s85$1@online.de>,
>> Jonathan Groß <pge03cnx@studserv.uni-leipzig.de> wrote:
>>
>>> Hello there,
>>>
>>> I want to init my Test-Object with an initial value, but it doesn't
>>> work.
>>> What's wrong or how can it be done?
>>>
>>> #import <objc/Object.h>
>>>
>>> @interface Test: Object
>>>
>>> {
>>> int L;
>>> int array[L];
>>> }
>>
>>
>> if your goal is to allocate an array of 'L' elements, the above will
>> not work, as 'L' is not known at compile time.
>>
>>
>> @interface Test : Object {
>> int L;
>> int *array;
>> }
>> -(Test *) initWith: (int) i
>> {
>> if ((self = [super init]) != nil) {
>> L = i;
>> array = (int *)malloc(L * sizeof(int));
>> }
>> return self;
>> }
>
>
> Thanks. This did work!
only if malloc succeeded, otherwise you will get a crash next time you
access an element. This should be better:
-(Test *) initWith: (int) i
{
self = [super init];
if (!self) {
// process initialization error...
// exit or throw exception
}
L = 0;
array = malloc(i * sizeof(*array));
if (!array) {
// process allocation error...
// exit or throw exception
}
L = i;
return self;
}
a+, ld.
-
Re: init array with instance
Graham J Lee <uk.ac.ox.physics.teaching@leeg.invalid> wrote:
>
> Yup, you're right about C99, and I was wrong and misleading. I was
> thinking of flexible arrays, which GNU C (at least) supports as long as
> they're the last element of the struct (effectively by malloc()ing past
> the end of the struct).
Note that C "allows" these as well, although GNU C has the added
convenience of allowing you to specify a 0-length array, whereas normal C
forces you to put in a 1 and then play games with your sizes to take it
into account.
> ObjC *doesn't* allow them, because it would be
> a right mess trying to deal with that and subclassing would effectively
> become impossible.
If you aren't subclassed then you can do the same thing as with structs.
Making sure extra memory gets allocated can be tricky, though, since it's
usually the root object that takes care of that for you. But if you didn't
mind being evil you could override +alloc and stick a variable-length
array at the end of your class.
--
Michael Ash
Rogue Amoeba Software
-
Re: init array with instance
Laurent Deniau <laurent.deniau@cern.ch> wrote:
>
> only if malloc succeeded, otherwise you will get a crash next time you
> access an element. This should be better:
>
> -(Test *) initWith: (int) i
> {
> self = [super init];
> if (!self) {
> // process initialization error...
> // exit or throw exception
> }
>
> L = 0;
> array = malloc(i * sizeof(*array));
> if (!array) {
> // process allocation error...
> // exit or throw exception
> }
> L = i;
>
> return self;
> }
While technically this is very true and never a bad idea, I'll note that
checking for allocation failures on UNIX is the exception rather than the
rule, and explicit allocation failures are unlikely to happen anyway. Much
more likely is that you'll get a pointer that isn't valid yet, and then
the OS will hang or kill your process when you try to access it and the OS
discovers it can't fulfill its promise. While it doesn't hurt to check for
failure, it will only catch a small proportion of the problems.
--
Michael Ash
Rogue Amoeba Software
Similar Threads
-
By Application Development in forum Javascript
Replies: 5
Last Post: 12-04-2007, 07:04 PM
-
By Application Development in forum lisp
Replies: 3
Last Post: 11-09-2007, 07:41 PM
-
By Application Development in forum c++
Replies: 4
Last Post: 09-12-2007, 07:04 AM
-
By Application Development in forum labview
Replies: 2
Last Post: 07-25-2007, 11:40 AM
-
By Application Development in forum verilog
Replies: 4
Last Post: 03-16-2006, 01:36 AM