d

KB/C/C++ 2007.07.30 22:07
 

mtd_info

mtd_info는 메모리 장치의 특성을 나타내는 구조체


59 struct mtd_info {
60 u_char type;
61         u_int32_t flags;
62         u_int32_t size// Total size of the MTD
63
64         /* "Major" erase size for the device. Naive users may take this
65          * to be the only erase size available, or may use the more detailed
66          * information below if they desire
67          */
68         u_int32_t erasesize;
85
86         // Kernel-only stuff starts here.
87         char *name;
88         int index;
89
90         // oobinfo is a nand_oobinfo structure, which can be set by iotcl (MEMSETOOBINFO)
91         struct nand_oobinfo oobinfo;
92         u_int32_t oobavail;  // Number of bytes in OOB area available for fs
93
94         /* Data for variable erase regions. If numeraseregions is zero,
95          * it means that the whole device has erasesize as given above.
96          */
97         int numeraseregions;
98         struct mtd_erase_region_info *eraseregions;
99
100         /* This really shouldn't be here. It can go away in 2.5 */
101         u_int32_t bank_size;
102
103         int (*erase) (struct mtd_info *mtd, struct erase_info *instr);
104
105         /* This stuff for eXecute-In-Place */
106         int (*point) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char **mtdbuf);
107
108         /* We probably shouldn't allow XIP if the unpoint isn't a NULL */
109         void (*unpoint) (struct mtd_info *mtd, u_char * addr, loff_t from, size_t len);
110
111
112         int (*read) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
113         int (*write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);
114
115         int (*read_ecc) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel);
116         int (*write_ecc) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel);
117
118         int (*read_oob) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
119         int (*write_oob) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);
120
121         /*
122          * Methods to access the protection register area, present in some
123          * flash devices. The user data is one time programmable but the
124          * factory data is read only.
125          */
126         int (*get_fact_prot_info) (struct mtd_info *mtd, struct otp_info *buf, size_t len);
127         int (*read_fact_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
128         int (*get_user_prot_info) (struct mtd_info *mtd, struct otp_info *buf, size_t len);
129         int (*read_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
130         int (*write_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
131         int (*lock_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len);
132
133         /* kvec-based read/write methods. We need these especially for NAND flash,
134            with its limited number of write cycles per erase.
135            NB: The 'count' parameter is the number of _vectors_, each of
136            which contains an (ofs, len) tuple.
137         */
138         int (*readv) (struct mtd_info *mtd, struct kvec *vecs, unsigned long count, loff_t from, size_t *retlen);
139         int (*readv_ecc) (struct mtd_info *mtd, struct kvec *vecs, unsigned long count, loff_t from,
140                 size_t *retlen, u_char *eccbuf, struct nand_oobinfo *oobsel);
141         int (*writev) (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen);
142         int (*writev_ecc) (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to,
143                 size_t *retlen, u_char *eccbuf, struct nand_oobinfo *oobsel);
144
145         /* Sync */
146         void (*sync) (struct mtd_info *mtd);
147
148         /* Chip-supported device locking */
149         int (*lock) (struct mtd_info *mtd, loff_t ofs, size_t len);
150         int (*unlock) (struct mtd_info *mtd, loff_t ofs, size_t len);
151
152         /* Power Management functions */
153         int (*suspend) (struct mtd_info *mtd);
154         void (*resume) (struct mtd_info *mtd);
155
156         /* Bad block management functions */
157         int (*block_isbad) (struct mtd_info *mtd, loff_t ofs);
158         int (*block_markbad) (struct mtd_info *mtd, loff_t ofs);
159
160         struct notifier_block reboot_notifier/* default mode before reboot */
161
162         void *priv;
163
164         struct module *owner;
165         int usecount;
166 };


플랫폼 디바이스 드라이버

플랫폼 드라이버 s3c2440_nand_driver 는 다음과 같이 정의된다.
Linux 2.6에서 나오는 Platform Device Driver model이다.
KObject을 기반으로, 객체 기반의 계층적 디바이스 드라이버 모델이다. (마치 Windows WDM처럼)
등록된 버스 디바이스가 있고, 버스에 새로운 디바이스가 붙으면 버스 드라이버가 디바이스를 탐지해서 해당 디바이스에 맞는 디바이스 드라이버를 구동하는 식이다.

아래는 플랫폼 디바이스 정의다.
16 struct platform_device {
17         const char      * name;
18         u32             id;
19         struct device   dev;
20         u32 num_resources;
21         struct resource * resource;
22 };


아래는 플랫폼 드라이버 정의다.
47 struct platform_driver {
48         int (*probe)(struct platform_device *);
49         int (*remove)(struct platform_device *);
50         void (*shutdown)(struct platform_device *);
51         int (*suspend)(struct platform_device *, pm_message_t state);
52         int (*resume)(struct platform_device *);
53         struct device_driver driver;
54 };

예로 s3c2440의 nand platform driver는 다음처럼 정의되고,
705 static struct platform_driver s3c2440_nand_driver = {
706         .probe          = s3c2440_nand_probe,
707         .remove         = s3c2410_nand_remove,
708         .driver         = {
709                 .name   = "s3c2440-nand",
710                 .owner  = THIS_MODULE,
711         },
712 };

device는 아래처럼 정의된다.
120 /* NAND Controller */
121
122 static struct resource s3c_nand_resource[] = {
123         [0] = {
124                 .start = S3C2410_PA_NAND,
125                 .end   = S3C2410_PA_NAND + S3C24XX_SZ_NAND - 1,
126                 .flags = IORESOURCE_MEM,
127         }
128 };

130 struct platform_device s3c_device_nand = {
131         .name             = "s3c2410-nand",
132         .id               = -1,
133         .num_resources    = ARRAY_SIZE(s3c_nand_resource),
134         .resource         = s3c_nand_resource,
135 };

일단 smdk2440 board machine init할때 nand 플랫폼 디바이스는 등록된다.


112 static struct platform_device __initdata *smdk_devs[] = {
113         &s3c_device_nand,
114 };

102 static struct s3c2410_platform_nand smdk_nand_info = {
103         .tacls          = 20,
104         .twrph0         = 60,
105         .twrph1         = 20,
106         .nr_sets        = ARRAY_SIZE(smdk_nand_sets),
107         .sets           = smdk_nand_sets,
108 };


116 void __init smdk_machine_init(void)
117 {
118         /* Configure the LEDs (even if we have no LED support)*/
119
120         s3c2410_gpio_cfgpin(S3C2410_GPF4, S3C2410_GPF4_OUTP);
121         s3c2410_gpio_cfgpin(S3C2410_GPF5, S3C2410_GPF5_OUTP);
122         s3c2410_gpio_cfgpin(S3C2410_GPF6, S3C2410_GPF6_OUTP);
123         s3c2410_gpio_cfgpin(S3C2410_GPF7, S3C2410_GPF7_OUTP);
124
125         s3c2410_gpio_setpin(S3C2410_GPF4, 1);
126         s3c2410_gpio_setpin(S3C2410_GPF5, 1);
127         s3c2410_gpio_setpin(S3C2410_GPF6, 1);
128         s3c2410_gpio_setpin(S3C2410_GPF7, 1);
129
130         s3c_device_nand.dev.platform_data = &smdk_nand_info;
131
132         platform_add_devices(smdk_devs, ARRAY_SIZE(smdk_devs)); <--- 여기
133
134         s3c2410_pm_init();
135 }



mtd_blktrans_ops

35
struct mtd_blktrans_ops {
36         char *name;
37         int major;
38         int part_bits;
39
40         /* Access functions */
41         int (*readsect)(struct mtd_blktrans_dev *dev,
42                     unsigned long block, char *buffer);
43         int (*writesect)(struct mtd_blktrans_dev *dev,
44 unsigned long block, char *buffer);
45
46         /* Block layer ioctls */
47         int (*getgeo)(struct mtd_blktrans_dev *dev, struct hd_geometry *geo);
48         int (*flush)(struct mtd_blktrans_dev *dev);
49
50         /* Called with mtd_table_mutex held; no race with add/remove */
51         int (*open)(struct mtd_blktrans_dev *dev);
52         int (*release)(struct mtd_blktrans_dev *dev);
53
54         /* Called on {de,}registration and on subsequent addition/removal
55            of devices, with mtd_table_mutex held. */
56         void (*add_mtd)(struct mtd_blktrans_ops *tr, struct mtd_info *mtd);
57         void (*remove_dev)(struct mtd_blktrans_dev *dev);
58
59         struct list_head devs;
60         struct list_head list;
61         struct module *owner;
62
63         struct mtd_blkcore_priv *blkcore_priv;
64 };

'KB > C/C++' 카테고리의 다른 글

d  (0) 2007.07.30
do{}while(0)를 하는 이유  (0) 2007.05.25
C와 어셈블리 호출  (0) 2006.08.15
VC++.NET 새 키워드  (0) 2006.06.28
cl.exe Episode XIII: Attack of the Standards: VC6, 7에서 C++ 표준 적용 사항  (0) 2006.06.28
typeof  (0) 2006.06.28
YOUR COMMENT IS THE CRITICAL SUCCESS FACTOR FOR THE QUALITY OF BLOG POST


오후 2:52 2007-05-25
do{}while(0)를 하는 이유
조경민 bro@shinbiro.com
===================================================


#define FOO  a = 1; printf("aa");
#define FOO  {a = 1; printf("aa");}


if( xx )
 FOO;
else
 a =2;


이런 경우 때문에 아래처럼 하는게 낫다.


#define FOO  do { a = 1; printf("aa"); }while(0)


 

'KB > C/C++' 카테고리의 다른 글

d  (0) 2007.07.30
do{}while(0)를 하는 이유  (0) 2007.05.25
C와 어셈블리 호출  (0) 2006.08.15
VC++.NET 새 키워드  (0) 2006.06.28
cl.exe Episode XIII: Attack of the Standards: VC6, 7에서 C++ 표준 적용 사항  (0) 2006.06.28
typeof  (0) 2006.06.28
YOUR COMMENT IS THE CRITICAL SUCCESS FACTOR FOR THE QUALITY OF BLOG POST


http://blog.naver.com/ziralist?Redirect=Log&logNo=8034854

어셈블리
http://kcjeong.cbu.ac.kr/%5Cworking%5Csp%5C04.ppt

'KB > C/C++' 카테고리의 다른 글

d  (0) 2007.07.30
do{}while(0)를 하는 이유  (0) 2007.05.25
C와 어셈블리 호출  (0) 2006.08.15
VC++.NET 새 키워드  (0) 2006.06.28
cl.exe Episode XIII: Attack of the Standards: VC6, 7에서 C++ 표준 적용 사항  (0) 2006.06.28
typeof  (0) 2006.06.28
YOUR COMMENT IS THE CRITICAL SUCCESS FACTOR FOR THE QUALITY OF BLOG POST


VC++.NET 새 키워드

KB/C/C++ 2006.06.28 16:18
Deep C++  
Optional Equipment Package

Bobby Schmidt
Microsoft Corporation

June 11, 2002

In my previous column, I survey new language-conformance features in Microsoft® Visual C++® .NET. This time I look at some new Microsoft-specific language extensions. (As I've cautioned in similar situations, the list of features I show here is representative, not canonical.)

The C and C++ standards let implementers (such as Microsoft) extend the standard language and library, so long as the presence of the extensions doesn't harm standard-conformant code. This attitude is consistent with the language committees' philosophy of allowing innovation without forcing programmers to pay for what they don't use. While Visual C++ .NET is not flawless in this regard, it is leagues beyond previous versions.

Distressingly, the compiler options enabling these extensions are inconsistently applied. In theory, /Za disables language extensions, while /Ze (which is on by default) enables them. In practice, some of the extensions work with /Za, some don't. Adding to the fun: throwing /clr enables some extensions, regardless of /Za or /Ze. If there's a method in the madness, I sure can't divine it.

Naming Extensions
Many of the extensions manifest as Microsoft-specific keywords and identifiers. To prevent such extensions from stomping on top of other names, the standards partition the set of all possible names into three domains:

Some specific names are explicitly reserved by the standards. In the C standard, the reserved names are macros, keywords, and global-scope declarations. In the C++ standard, most reserved names that would be global in C are elements of namespace std.
Of the remaining possible names, those matching certain patterns are reserved for language and library implementers. The patterns differ slightly between C and C++; I summarize them below.
All other names are reserved for you, the programming proletariat. You still have to duke it out with vendors of third-party libraries and your own team members to avoid name clashes, but that's a problem beyond the standard's concern. And if you use a name that's reserved for the standard or implementers, you're on your own; compilers aren't required to diagnose such usage, and I don't know of any that do.
Names Microsoft May Usurp
The C standard specifically reserves these names for implementers of the standard C language and library:

All global names starting with _ (single underscore).
All names starting with _A, _B, …, _Z—that is, an underscore followed by an upper-case letter.
All names starting with __ (double underscore).
To make things simple, the style rule I use for C is:

Avoid all names starting with _.
This is overly restrictive but safe and easy to apply.

The C++ standard reserves a slightly different name set:

All global names starting with _, just as in C.
All names starting with _A, _B, …, _Z—again, just as in C.
All names containing __ anywhere, not just at the start. I suspect the C++ committee broadened this rule to better allow name decoration/mangling.
The style rule I use for C++ is a superset of the C++ rule:

Avoid all names starting with _.
Avoid all names containing __.
Unless you have some compelling reason to keep separate C and C++ style rules, I suggest you use the C++ rules for both languages. Note that you can safely use trailing single underscores in either language. This is the naming style I use for inclusion guards, data members, and other "private" names.

Stealth Name Usage
Implementers can use their names in non-obvious contexts. In particular, the names can show up as intrinsic statements or library calls that don't appear in the source (even preprocessed), but do appear in the object file. This is the real danger of using these names: You may scrub your standard-library headers and interfaces, and convince yourself that a certain name is available, only to find that your implementer has injected the name into your code during translation.

For illustration, compile the small example

#include <math.h>

int main(void)
   {
   return sin(0.);
   }

as either C or C++. In the mixed source/assembly listing generated by cl /Fas, you'll see this code implementing the return statement:

fldz
push   ecx
push   ecx
fstp   QWORD PTR [esp]
call   _sin
pop   ecx
pop   ecx
call   __ftol2

The generated code contains two hidden calls to implementation-specific functions, both of which have names following the standards' name-reservation rules.

The Managed Extensions for C++
I will dissect managed extensions in future columns. Here I just want to give the barest introduction.

According to this page in the Visual C++ .NET documentation, 18 keywords "implement various features of the Managed Extensions for C++." The strong suggestion: These keywords are the Managed Extensions for C++, or at least form the core of those extensions. The further implication: The keywords require compilation with /clr, and are therefore new to Visual C++ .NET. (Otherwise they wouldn't be "managed" extensions.)

I find the documentation ambiguous. Of the 18 keywords:

Private, protected, and public aren't specific to Microsoft, although in managed code they can be used in non-standard ways.
__finally is available in Visual C++ 6.0.
None of these four requires compilation /clr.

The remaining 14 keywords are new to Visual C++ .NET. Of those, three don't require /clr:

__event
__identifier
__interface
Of the remaining 11 that do require /clr, five can appear in native functions:

__abstract
__nogc
__sealed
__try_cast
__value
This leaves six that are specific to managed functions:

__box
__delegate
__gc
__pin
__property
__typeof
Reading the product documentation more closely, I note that the reference pages for the 11 keywords requiring /clr, plus __identifier, are nested under the main reference page describing Managed Extensions in general. Maybe those 12 are the "real" Managed Extension keywords.

Then again, this page suggests the 14 new keywords are the real Managed Extension keywords.

Regardless, I mentally organize the new keywords into these usage buckets:

__abstract, __delegate, __event, __interface, and __property are kinds of declared entities.
__gc, __nogc, and __value define whether and how a type is managed.
__try_cast and __typeof interrogate the type system.
__box and __pin bridge the chasm between the managed and unmanaged worlds.
__sealed inhibits derivation.
__identifier harmonizes names among source languages.
In future columns devoted to managed development, I'll likely explore the extensions in these groupings.

Other Keywords
The following are other keyword extensions new to Visual C++ .NET:

__alignof is kindred to sizeof, an operator accepting a type operand and yielding a size_t byte count (in this case, the operand's alignment).
__assume passes hints to the code optimizer. According to the documentation, the optimizer assumes that the keyword's operand is true. An operand of 0 would appear to conflict with this assumption; yet bizarrely, the docs advocate __assume(0)! Apparently __assume(0) renders a particular swath of code unreachable. The documentation gives the specific example of __assume(0) after the default label in a switch statement. This tells the optimizer to assume the default case can't be reached.
__if_exists and __if_not_exists test—at compile time—for the presence or absence of a potentially declared name. They are analogous to #ifdef and #ifndef for symbols not stripped by preprocessing.
__debugbreak places a breakpoint. It appears equivalent to the Tester's Friend, a.k.a. __asm int 3.
__hook, __raise, and __unhook interact with __event declarations. __hook and __unhook associate and dissociate event handlers and events, while __raise raises events.
__noop can be used in place of a function name in a function-call expression. Any function arguments following __noop will not be evaluated. When I test __noop in other contexts, it appears to evaluate as int-type constant 0. Since the documentation says nothing about such usage, I'm not sure if this is supported behavior.
__super aliases one of a class's bases, depending on which base class best matches __super's usage and context. For singly inherited classes, __super is analogous to the Java keyword super and the C# keyword base.
__w64 treats an object as if it were 64-bit for diagnostic purposes only. I explore the __w64 keyword in a previous column.
In addition, the hoary storage-class extension __declspec supports these new attributes:

__declspec(align(...)) control's a user-defined type's alignment.
__declspec(deprecated) tags a function as obsolete or potentially unsupported. Calls to such functions generate compile-time warning C4996.
__declspec(noinline) prevents a function from being expanded inline. __declspec(noinline) is the moral opposite of the standard keyword inline.
All of the keywords work in both managed and native code. None requires /clr. And some even work in C:

__alignof
__assume
__debugbreak
__declspec
__noop
__w64
Language Lawyer Alert
I don't think that __noop technically qualifies as a keyword, since it can be used as a non-macro identifier:

int __noop; // OK

and real keywords can't:

int friend;    // error
int __alignof; // error

I'm not actually sure what to call __noop, given how its behavior changes depending on context:

int x = __noop; // OK, __noop evaluates as 0
__noop(++x);    // OK, __noop is not evaluated; neither is ++x
int __noop;     // OK, __noop is a normal identifier
__noop(++x);    // now this is an error, since __noop is an int

Alleged Keyword Extensions
The types __m64, __m128, __m128d, and __m128i hold 64-bit and 128-bit values. Several headers declare a large collection of new processor-specific intrinsic functions that manipulate these types. These intrinsic functions have the semantics of inline functions, but require no definition. Many of the "calls" map to a single assembly-language instruction.

The functions are declared in four headers:

mmintrin.h wraps Intel® MMX (multimedia extension) instructions.
xmmintrin.h and fvec.h wrap Intel Streaming SIMD Extensions (or SSE) instructions.
mm3dnow.h wraps Advanced Micro Devices (AMD) 3DNow!™ instructions.
Example:

#include <mmintrin.h> // declares intrinsics for Intel MMX

class MM_wrapper
    {
public:
    operator __m64() const // type wraps 64-bit MMX register value
        {
        return _mm_cvtsi32_si64(i_); // call to intrinsic function
        }
private:
    int i_;
    // ...
    };

The Visual C++ .NET docs claim that the types __m64, et al, are keywords, which implies the compiler knows about them natively. Yet my testing shows that the types aren't keywords at all:

int __m64; // OK, but should be an error if __m64 is a keyword

Instead, they are actually declared in the headers along with the intrinsic functions:

#include <mmintrin.h>

int __m64; // now an error

I consider the documentation's claim a bug. Further, because both the types and the intrinsic functions require inclusion of a header file, I don't consider either set a true language extension. At best, they are library extensions that the compiler treats as special cases when generating code.

The types and intrinsic functions work in both C and C++.

Other Data Types
Visual C++ 6.0 predefines the non-standard integer types __int8, __int16, __int32, and __int64. These types are miscible with, but separate from, the standard fundamental integer types:

void f(__int32)
    {
    }

void f(int) // OK, overload of f(__int32)
    {
    }

This works even though both __int32 and int are represented identically in generated code as 32-bit signed integers.

In Visual C++ .NET, the first three of these types are actually aliases for char, short, and int:

void f(__int32)
    {
    }

void f(int) // error, redefinition of f(__int32)
    {
    }

The only exception is __int64, which has no alias among the standard primitive types.

Pragmas
Pragmas are hybrid oddities. The preprocessor directive that introduces them (#pragma) is standard, and must be supported by every compiler. What comes after the directive is implementation-defined, and might not be supported by any compiler. (There are no standard pragmas.)

Visual C++ .NET supports a new set of pragmas that Visual C++ 6.0 does not. Indeed, there's no guarantee that any other compiler supports them. Nonetheless, major compiler vendors would be wise to at least silently absorb Microsoft's pragmas; otherwise source translated by Visual C++—the galactic arm's most popular compiler—will likely generate warnings on those other systems.

The new pragmas:

conform throttles the behavior of compiler option /Zc:forScope, which controls the scope of declaration within for statements. I discuss this option here.
deprecated lists functions that are deprecated (in the C and C++ sense, not in the real English sense). It is functionally equivalent to declaring those same functions with __declspec(deprecated).
managed and unmanaged control whether a set of functions is managed or unmanaged. It is meaningful only with the /clr compiler option.
runtime_checks governs the behavior of compiler option /RTC, which I describe here.
section creates a section (with optional attributes) in an object file.
In addition, the old pragma pack has a new option show that displays the current packing alignment (as a warning) during compile time.

Other Preprocessor Directives
Visual C++ .NET supports two non-standard preprocessor directives: #using and #import. Both are available in only C++, not C. Both are also analogous to #include, in that they introduce "source" from an external context during C++ translation.

#using is new to Visual C++ .NET. (And no, it has nothing to do with the standard keyword using.) It imports metadata into a managed program, and thus must be used with the /clr compiler option. In an odd quirk, the #using directive appears in the preprocessed output generated by options /E, /EP, or /P. You can verify this by compiling the tiny example

#using <mscorlib.dll>

with cl /clr /EP and examining the preprocessor output.

#import is available in Visual C++ 6.0. It translates a native type library into a pair of C++ header files: the primary or .tlh header, and the secondary or .tli header. In effect, #import is the native (and primitive) analogue of #using. Like #using, #import works only in C++.

#import supports a large number of attributes that affect the generated headers. Visual C++ .NET extends #import with three new attributes:

embedded_idl preserves attribute-generated code in the primary header file.
no_dual_interfaces causes the wrapper for dual-interface methods to call those methods through IDispatch::Invoke instead of through a v-table.
no_smartpointers omits smart pointer (_com_ptr_t) declarations in the generated interfaces.
In counterpoint to #using, #import directives are executed and replaced in preprocessed output. To witness a stupendous example, compile

#import <mscorlib.tlb>

with cl /EP /Zs. On my system, the resulting preprocessed output stream is over 200,000 lines and 2,000,000 characters long.

Predefined Macros
Visual C++ .NET defines several new non-standard macros.

Ho-Hum
_MANAGED is defined as 1 for code compiled with /clr, and undefined otherwise.
Mildly Arousing
__COUNTER__ is a compile-time counter. It evaluates to the int constant 0 the first time it's expanded, 1 the second time, and so on:

#include <iostream>
using namespace std;

int main()
    {
    cout << __COUNTER__ << endl;
    cout << __COUNTER__ << endl;
    cout << __COUNTER__ << endl;
    }

/* run-time result:
0
1
2
*/

Note that the counter increments happen at compile-time, not at run time:

#include <iostream>
using namespace std;

int main()
    {
    for (int i = 0; i != 3; ++i)
        cout << __COUNTER__ << endl;
    }

/* run-time result:
0
0
0
*/

Titillating
Three new macros relate to an enclosing function's name or signature:

__FUNCTION__ expands to the function's name.
__FUNCSIG__ expands to the function's friendly (human-readable) signature.
__FUNCDNAME__ expands to the function's decorated (software-readable) signature.
Here's a somewhat elaborate example of each:

#include <iostream>
using namespace std;

typedef int INT;

template<typename T>
INT const volatile __cdecl abc()
    {
    cout << __FUNCTION__ << endl;
    cout << __FUNCSIG__ << endl;
    cout << __FUNCDNAME__ << endl;
    return 0;
    }

int main()
    {
    abc<int const volatile>();
    }

When run, this program produces

abc<int const volatile >
volatile const int __cdecl abc<int const volatile >(void)
?abc@?$@$$CDH@@YA?DHXZ

Note that the original source's appearance is not perfectly preserved in the friendly signature:

() is replaced with (void).
INT is replaced with the type it aliases (int).
The return type's CV-qualifier sequence const volatile is reordered as volatile const.
Those CV-qualifiers appear after int in the return type.
The same sequence (const volatile int) appears as both the return type and the template argument in the original source. Oddly, the macro expansion scrambles the return-type order, but preserves the template-argument order.

Because the template argument can't be deduced, the template specialization must be explicit. If you rewrite the template so that the argument is deducible:

#include <iostream>
using namespace std;

typedef int INT;

template<typename T>
INT const volatile __cdecl abc(T = T())
    {
    cout << __FUNCTION__ << endl;
    cout << __FUNCSIG__ << endl;
    cout << __FUNCDNAME__ << endl;
    return 0;
    }

int main()
    {
    abc<int const volatile>();
    }

the results change:

abc
volatile const int __cdecl abc(volatile const int)
?abc@@YA?DHH@Z

Unsurprisingly, the function parameter is no longer void. But quite surprisingly, the function name is now just the template name abc, rather than the actual specialization abc<const volatile int>. The macros act as if abc is an ordinary (non-template) function overload.

The macro troubles evidence a more fundamental flaw: the compiler and linker conspiring to incorrectly decorate certain kinds of function signatures. While I don't show it here, this problem affects Visual C++'s standard conformance. And since we now care about such conformance, presumably we'll fix the flaw in a future Visual C++ release.

Sundries:

The macros must appear in the scope of a function body.
While the documentation is silent on this point, my testing shows each expanded value to have type char [N] rather than the char const [N] you might expect.
The macros are not expanded in preprocessed output generated by compiler options /E, /EP, and /P.
Exceptions
Visual C++ .NET supports a funky extension to normal exception-specification syntax:

void f() throw(...)
    {
    // ...
    }

According to the documentation:

throw(...) tells the compiler that a function could throw an exception. This is useful if you want your functions to explicitly specify whether or not they will throw exceptions.
From what I can tell, there's no semantic difference between the Microsoft-specific

void f() throw(...)

and the standard-conformant

void f()

I think the benefit (such as it is) lies in the syntax: By explicitly tagging a function with throw(...), you can communicate intention more clearly. Used diligently and deliberately, void f throw(...) can say to users "I've analyzed this function's exception characteristics, and have found that the function might throw, although I can't yet guarantee what it could throw." void f() could say that, yes; but it could also say "I haven't analyzed this function's exception characteristics," or "this function was originally written in C," or "this function calls into code written in another language."

If you adopt Microsoft's throw extension, you can tag every function with an exception specification:

void f1() throw();       // f1 throws nothing
void f2() throw(...);    // f2 may throw an unspecified exception
void f3() throw(T1, T2); // f3 may throw exception of type T1 or T2

Counterpoint
Some prominent colleagues believe that exception specifications are either a good idea implemented badly, or just a bad idea. Perhaps the most significant critic is Herb Sutter, who's researched and written about C++ exceptions more than anyone else I know.

Much of the trouble comes from the lack of static type checking on exception specifications:

void f() throw() // f claims to throw nothing, but...
    {
    throw 1;     // the compiler allows this anyway
    }

The specifications are checked only at run time; and even then the consequence is typically program termination, albeit with one last chance at program cleanup. Specifications can also incur a non-trivial speed or space cost at run time, especially if used indiscriminately. (To be fair: That's true as well for other C++ aspects, such as copy construction and template instantiation, yet we don't use that argument to justify wholesale avoidance of these features.)

I expect that specifications will be stay dynamically checked as a general rule, if only to allow interoperation with code lacking specifications. At best, I can envision two kinds of specifications in the future: those checked at run time much as they are today, and a separate set checked at compile time, somewhat like Java's. The latter would require a change to the C++ standard; you can find one such proposed change here.

Conversely, I won't be surprised if the C++ committee takes a different tack: voting exception specifications out of the standard, or at least tagging them as deprecated. Not every one of the committee's inventions has been a success; maybe we should admit exception specifications are a failed experiment and move on.

Attributes
As attributes warrant their own column, I show them only briefly here.

Here's a partial native example adapted from the Visual C++ docs:

#include <windows.h>

[module(name="MyLibrary")]
[uuid("2F5F63F1-16DA-11d2-9E7B-00C04FB926DA"), dual]
__interface IStatic::IDispatch
    {
    // ...
    HRESULT P1([in] long);    
    };

[cpp_quote("#include file.h")];

int main()
    {
    }

All of the bits in [] are attributes. Because standard C++ doesn't use such syntax, code outside the attributes is ignorant of and not directly affected by the pieces inside. This mechanism cleanly and obviously separates the extended features from the standard ones.

The nature and meaning of attributes depends on their context:

In native code, attributes enhance interaction with COM and type libraries, and generalize a similar concept from IDL and ODL. They are specific to Visual C++.
In managed code, custom attributes extend metadata, which is the CLR analogue of type libraries. They are available in all CLR-targeting languages, not just Visual C++.
Coda
Next time I'll summarize significant standard-conformant language features still missing in Visual C++ .NET.

'KB > C/C++' 카테고리의 다른 글

do{}while(0)를 하는 이유  (0) 2007.05.25
C와 어셈블리 호출  (0) 2006.08.15
VC++.NET 새 키워드  (0) 2006.06.28
cl.exe Episode XIII: Attack of the Standards: VC6, 7에서 C++ 표준 적용 사항  (0) 2006.06.28
typeof  (0) 2006.06.28
code profiler  (0) 2006.04.17
YOUR COMMENT IS THE CRITICAL SUCCESS FACTOR FOR THE QUALITY OF BLOG POST


MSDN에서 펌
Deep C++  
cl.exe Episode XIII: Attack of the Standards


User-defined Conversions
Conversion from a source type S to a target type T may require a sequence of intermediate implicit conversions along the way. In the simple example

typedef int S[10];
typedef void const *T;

S s;
T t;

t = s; // implicit conversion from S to T

the overall conversion from S to T comprises three implicit conversions in this order:

The array-to-pointer conversion from S to int *, which is really from int [10] to int *.
The pointer conversion from int * to void *.
The qualification conversion from void * to T, which is really from void * to void const *.
You can make any or all of these intermediate steps explicit without changing the meaning:

t = s;                      // equivalent to...
t = (int *) s;              // equivalent to...
t = (void *) s;             // equivalent to...
t = (T) (int *) s;          // equivalent to...
t = (T) (void *) (int *) s;

These particular implicit conversions are called standard conversions, as they are required by the C++ standard and predefined by the compiler. You can also create user-defined conversions for your own class types. In

class S
    {
public:
    operator int();
    };

int f()
    {
    return S(); // implicit conversion from S to int
    }

the final return statement implicitly converts from S to int through the user-defined conversion S::operator int(). Similarly, the return statement in

class T
    {
public:
    T(int);
    };

T f()
    {
    return int(); // implicit conversion from int to T
    }

implicitly converts int to T with the user-defined conversion T::T(int).

If you combine these two:

class S
    {
public:
    operator int() const;
    };

class T
    {
public:
    T(int);
    };

T f()
    {
    return S(); // implicit S to int, implicit int to T
    }

the return statement requires two implicit user-defined conversions:

From S to int through S::operator int().
From int to T through T::T(int).
With a standard-conforming C++ implementation, this code won't work: the standard allows at most one implicit user-defined conversion on a single value. Visual C++ 6.0 incorrectly allows the two-conversion sequence anyway, without any clue something's amiss. Visual C++ .NET also allows it, but at least flags the sequence with a warning:

warning C4927: illegal conversion; more than one user-defined
conversion has been implicitly applied while calling the constructor
'T::T(int)'

If you tell Visual C++ .NET to treat this warning as an error (cl /we4927), then the compiler behaves according to the standard and won't accept the code.

To render the example standard conformant, make one of the implicit conversions explicit with either

return T(S()); // implicit S to int, explicit int to T

or

return int(S()); // explicit S to int, implicit int to T

-------------------


Member Initialization
Most static members must be initialized outside the class declaring them. This is true even for const members:

class X1
    {
    static double const d = 1; // error
    };

class X2
    {
    static double const d; // OK
    };

double const X2::d = 2; // OK

This truth can lead to awkward dichotomies between constants declared inside and outside of classes, and between function members defined inside and outside of the declaring classes:

int const n = 10;

class X
    {
public:
    static int const n; // X::n is declared but not initialized
    void f1()
        {
        int a[::n]; // OK, ::n's value is known
        }
    void f2()
        {
        int a[X::n]; // error, X::n's value isn't known yet
        }
    void f3();
    };

int const X::n = 10; // X::n is now initialized

void X::f3()
    {
    int a[X::n]; // OK, X::n's value is now known
    }

Whenever a member's behavior depends on where that member is defined, confusion and trouble often follow. To prevent this particular trouble, old-school C++ programmers often employ the enum trick:

// ...

class X
    {
public:
    /*static int const n;*/
    enum
        {
        n = 10
        };
    // ...
    void f2()
        {
        int a[X::n]; // now OK, X::n's value is known
        }
    // ...
    };

/*int const X::n = 10;*/

// ...

The enum trick is a first-class hack. It works, but at the cost of subverting the general intent of enumeration types. It is also limited to the underlying integer type implementing the enumeration, which may vary from compiler to compiler, or even among enumerations with the same compiler. Since you can't specify the underlying enumeration type, you can't directly control or even predict how X::n is treated when converted to that unknown type. (The Visual C++ Managed Extensions allow you to specify the underlying type of managed enumerations. I'm aware of no extension for specifying the type of unmanaged or native enumerations.)

Happily, you don't have to care about any of this anymore. Fairly late in the standardization game, the C++ standards committee patched the C++ standard to let static integer constants be initialized in their declarations:

class X
    {
public:
    static int const n = 10; // initialization OK
    void f2()
        {
        int a[X::n]; // OK
        }
    };

int const X::n = 10; // now an error -- multiple initialization
int const X::n;      // definition OK, but might not be required

Visual C++ .NET compiles this properly. Visual C++ 6.0 interprets the initialization of X::n as an illegal pure virtual function declaration.

The feature has restrictions:

Members must be static.
Members must be const.
Members must have some integral or enumeration type.
The initializing value must be an integral constant expression.
Members can be initialized at most once. If you initialize them within the class, you can't initialize them again in their definitions.


----------------

Scope
I discuss this at length in my previous column, so I won't belabor it here. In short, Visual C++ 6.0 does not properly scope declarations in a for statement when Microsoft-specific language extensions are enabled (cl /Ze):

for (int i;;)
    ;
i = 0; // OK, i is (incorrectly) still available here

Visual C++ .NET maintains the Visual C++ 6.0 behavior by default. But if you use the compiler option /Zc:forScope along with /Ze, Visual C++ .NET observes the standard-required behavior:

for (int i;;)
    ;
i = 0; // error, i is (correctly) no longer available

Note that both compiler versions maintain proper for scope when language extensions are disabled (cl /Za).

-----------

Return from Main
Many programmers reckon that all programs terminate through a return statement in main:

int main()
    {
    // ...
    return 0;
    }

But consider:

#include <cstdlib>

int main()
    {
    std::exit(1);
    return 0; // unreachable code
    }

or

int main()
    {
    throw 1;
    return 0; // unreachable code
    }

Clearly a program can terminate without actually encountering a return statement in main. The C++ standard accordingly allows main to be defined without any return statement at all, or with only some code paths executing a return. Where main returns normally without benefit of a return statement, the program acts as if main actually exited with return 0.

The small program

int main(int argc, char **argv)
    {
    if (argc == 1)
        return 1;  // exit point #1
    if (argc == 2) // exit point #2
        throw 2;
    }              // exit point #3

exits in one of three ways:

If argc is 1, the program explicitly returns 1 to the calling environment.
If argc is 2, the program returns nothing to the calling environment, but instead terminates with an exception.
If argc is any other value, the program implicitly returns 0 to the calling environment.
Visual C++ .NET gets this right, while Visual C++ 6.0 issues a warning about some code paths not returning a value.

On a related note: Visual C++ 6.0 allows

void main()
    {
    }

in violation of the C++ standard. Entirely too many C++ programmers grow up believing that main returning void is standard-conformant, simply because Microsoft's compilers allow it. I've lost count of how many times I've educated inexperienced programmers that just because Visual C++ 6.0 allows a feature doesn't mean the standard allows it.

I'm thrilled to report that Visual C++ .NET flags this same construct with:

warning C4326: return type of 'main' should be 'int' instead of 'void'

To properly treat this warning as an error, compile with cl -We4326.

---------------

Other Return Types
If a function in a derived class shares the same name and parameter list as a virtual function in a base class, then the derived-class function overrides the base-class function, and can be called polymorphically. If the names are the same, but the parameter lists differ or the base-class function is non-virtual, then the derived-class function hides the base-class function. To illustrate:

class Base
    {
public:
    virtual void f1();
    virtual void f2();
    };

class Derived : public Base
    {
public:
    virtual void f1();
    virtual void f2(int = 0);
    };

int main()
    {
    Derived d;
    Base &b = d;
    b.f1(); // OK, calls Derived::f1
    b.f2(); // OK, calls Base::f2
    }

Derived::f1 overrides Base::f1, since both parameters lists are the same. Conversely, Derived::b2 hides (but does not override) Base::f2—even though Base::f2 and Derived::f2 can be called with the same argument lists, their parameter lists are different.

The language rules once required that overriding functions always share return types:

class Base
    {
public:
    virtual void f1();
    virtual void f2();
    };

class Derived : public Base
    {
public:
    virtual int f1();    // error
    virtual int f2(int); // OK
    };

Derived::f1 properly overrides Base::f1 as before. Derived::f2 also overrides Base::f2; but because the return types differ, the compiler flags an error.

This restriction is nettlesome when you want the relationship between the return types to parallel the inheritance:

class Base
    {
public:
    virtual Base &clone() = 0;
    };

class Derived : public Base
    {
public:
    virtual Derived &clone();
    };

Because the older overriding rules didn't allow this, you had to resort to an unsatisfying compromise:

class Base
    {
public:
    virtual Base &clone() = 0;
    };

class Derived : public Base
    {
public:
    virtual Base &clone(); // override
    };

int main()
    {
    Derived d;
    Base    &b1 = d.clone(); // OK, but...
    Derived &d1 = d.clone(); // unintuitively an error
    }

To let such constructions work, the C++ committee changed the language rules. Overriding return types may now differ from each another if they relate by inheritance as well:

The return types either are both pointers or are both references—types that can engage in polymorphic behavior. Call the base-class function's possible return types B * and B &, and the derived-class function's D * and D &.
B is directly or indirectly an unambiguous and accessible base of D.
B * and D *, or B & and D &, have the same CV qualification. Additionally, D is at least as CV-qualified as B.
According to the standard, such return types are covariant with the polymorphic classes using them. Modifying my example in light of covariance yields

class Base
    {
public:
    virtual Base &clone() = 0;
    };

class Derived : public Base
    {
public:
    virtual Derived &clone(); // override
    };

int main()
    {
    Derived d;
    Base    &b1 = d.clone(); // OK, and...
    Derived &d1 = d.clone(); // OK!
    }

As you doubtless expect by now, Visual C++ 6.0 chokes on covariant types:

'Derived::clone' : overriding virtual function differs from
'Base::clone' only by return type or calling convention

while Visual C++ .NET accepts them.

Although covariant return types share an inheritance relationship with each other, they need not share that relationship with the classes using them:

class B
    {
    };

class D : public B
    {
    };

// ...

class Base
    {
    virtual B &f();
    };

class Derived : public Base
    {
    virtual D &f(); // override
    };

B and D are covariant with Base and Derived, even though the respective inheritance relationships are completely separated.

Covariance allows the structure among a family of classes to be paralleled in a family of return types. In effect, the return types—and the relationship among them—are a metaphor or mapping of the classes. While I understand the attractiveness and symmetry in this approach, I find covariance somewhat arbitrary. Consider what happens if you change clone to "return" through an outbound argument:

class Base
    {
public:
    virtual void clone(Base *&) = 0;
    };

class Derived : public Base
    {
public:
    virtual void clone(Derived *&); // hides Base::clone
    };

Because Derived::clone and Base::clone have different parameter lists, the former hides the latter. To make Derived::clone an override, you must go back to

class Base
    {
public:
    virtual void clone(Base *&) = 0;
    };

class Derived : public Base
    {
public:
    virtual void clone(Base *&); // overrides Base::clone
    };

which just resurrects the original problem:

Derived d, *dp;
Base *bp;
d.clone(bp); // OK, but...
d.clone(dp); // error

Covariance can't help you if you return values by argument—it works only for actual function return values. As I say, this strikes me as somewhat arbitrary.

(Before language lawyers descend: I understand that parameter covariance would likely complicate the grammar, if indeed such covariance could even be specified. I'm simply pointing out that covariance seems more of a special case than a general solution.)

---------

Exception Handling
Before the great Deep C++ hiatus, I wrote at disturbing length about C++ exceptions. As I noted then, Visual C++ 6.0 fails to support several exception-handling features required by the standard. While Visual C++ .NET still falls short, it does finally allow function try blocks. Such blocks solve a problem normal try blocks can't: handling exceptions thrown before a function's body is actually entered.

In the definition

class X
    {
public:
    X(unsigned);
private:
    char *p;
    };

X::X(unsigned n) : p(new char[n]) // what if this throws?
    {
    try
        {
        // ... constructor code
        }
    catch (...)
        {
        }
    }

any exception thrown by new char[n] would occur before the constructor body is entered, and thus couldn't be caught by the constructor's exception handler. Recasting the try block as a function try block:

X::X(unsigned n)
try
        : p(new char[n])
    {
    // ... constructor code
    }
catch (...)
    {
    }

allows exceptions from the entire function, including the member initializer, to be caught.

Visual C++ 6.0 is completely ignorant of function try blocks. In fact, it gets so confused that it issues the same diagnostic twice:

error C2143: syntax error : missing ';' before try
error C2143: syntax error : missing ';' before try

I discuss function try blocks at some length in this earlier column.

---------

Templates
Visual C++ .NET fixes a few conformance problems involving templates.

Non-Type Template Parameters
Visual C++ .NET finally allows one of my pet features—finding the length of an array during compilation:

#include <stdlib.h> // defines size_t

template<typename T, size_t N>
size_t lengthof(T (&)[N])
    {
    return N;
    }

int main()
    {
    int a[10];
    lengthof(a); // calls lengthof<int, 10>
    }

If you masochistically compile this program with Visual C++ 6.0, you'll experience wondrous diagnostics:

error C2265: '<Unknown>' : reference to a zero-sized array is illegal
error C2266: '<Unknown>' : reference to a non-constant bounded array
is illegal
error C2784: 'unsigned int __cdecl lengthof(T (&)[1])' : could not
deduce template argument for ' (&)[1]' from 'int [10]'

With the older compiler, the best approximation of a proper lengthof has been

#define LENGTHOF(a) \
    (sizeof(a) / sizeof(*(a)))

We all have our fetishes, and this has been one of mine. I've written about lengthof versus LENGTHOF at, well, length in my CUJ columns (particularly here).

----------

Template Template Parameters
Template parameters may also be templates themselves, or what the standard calls template template parameters:

template<typename T>
class my_node
    {
    // ...
private:
    T value;
    my_node<T> *next;
    };

template<typename Value, template<typename T> class Node>
class container
    {
    // ...
private:
    Node<Value> *list;
    };

container<int, my_node> x;

Node is a template template parameter of container; my_node is the corresponding template template argument in x's definition.
-----------------

Template Friends
According to the Visual C++ team, the new compiler supports friends in templates "to some degree." Here's an example adapted from one in the C++ standard:

template<typename T>
class C2;

template<typename T>
void f2();

template<typename T>
class X
    {
    template<typename T1>
        friend class C1;
    template<typename T1>
        friend void f1();
    friend class C2< X<T> >;
    friend void f2< X<T> >();
    friend class C3;
    friend void f3();
    };

This all actually compiles with Visual C++ .NET, and encompasses the gamut of friends: templates, template specializations, and ordinary (non-template) classes and functions.

Visual C++ 6.0 completely loses the plot while interpreting this code, and the error messages show it. The paragon of diagnostic lucidity comes on line 11, at the first friend declaration:

error C2059: syntax error : '<end Parse>'

----------------------
Template Specialization
Visual C++ .NET now prevents multiple definitions of the same template specialization, at least for function templates:

typedef int INT;

template <typename T>
void f();

template<>
void f<int>()
    {
    }

template<>
void f<INT>() // redefines f<int>
    {
    }

Visual C++ 6.0 accepts the code while ignoring the second definition. Visual C++ .NET properly rejects this code, although the diagnostic is a bit untidy:

error C2084: function 'void f<int>(void)' already has a body
see previous definition of 'f@?$@H'

No, that's not profanity. It's the function's mangled or decorated name, which probably isn't supposed to be there.
---------------

'KB > C/C++' 카테고리의 다른 글

C와 어셈블리 호출  (0) 2006.08.15
VC++.NET 새 키워드  (0) 2006.06.28
cl.exe Episode XIII: Attack of the Standards: VC6, 7에서 C++ 표준 적용 사항  (0) 2006.06.28
typeof  (0) 2006.06.28
code profiler  (0) 2006.04.17
함수 링크 순서 정해주기  (0) 2005.10.28
YOUR COMMENT IS THE CRITICAL SUCCESS FACTOR FOR THE QUALITY OF BLOG POST


typeof

KB/C/C++ 2006.06.28 16:00
C++ 표준이라지만, VC6, 7.1에서는 지원 안되고, gcc에서는 지원되나보다. 그래서 난 이거 잘 모르고 있다 ㅎㅎ..

C++ 표준
http://std.dkuug.dk/jtc1/sc22/open/n2356/

stl에서 typeof 활용 gcc는 된다는 말
http://levites.pe.kr/phpBB/viewtopic.php?t=54&sid=199fb480eff5a54617bf2afec0b0bdc9

VC에서 지원하도록 꽁수.. 쓰고 싶은거 등록해야 하는 아픔이.
http://www.codeproject.com/vcpp/stl/typeof.asp

VC pre-defined인 __COUNTER__ (컴파일횟수)를 없앤 버전 소개에서 Boost이용한 typeof에 관한 얘기가 있음
http://article.gmane.org/gmane.comp.lib.boost.devel/102438
http://article.gmane.org/gmane.comp.lib.boost.devel/106995

템플리트를 이용한 접근방법
http://www.accu-usa.org/2000-05-Main.html

'KB > C/C++' 카테고리의 다른 글

VC++.NET 새 키워드  (0) 2006.06.28
cl.exe Episode XIII: Attack of the Standards: VC6, 7에서 C++ 표준 적용 사항  (0) 2006.06.28
typeof  (0) 2006.06.28
code profiler  (0) 2006.04.17
함수 링크 순서 정해주기  (0) 2005.10.28
RSA를 이해하기 위한 코드  (0) 2005.03.25
YOUR COMMENT IS THE CRITICAL SUCCESS FACTOR FOR THE QUALITY OF BLOG POST


code profiler

KB/C/C++ 2006.04.17 16:14
Visual C++ 2003
자체 프로파일러 없음, CLR은 현재 1.1 버전 만들고 있음 2005 Team suite버전에 추가될 듯

Devpartner profiler for free 사용
http://www.compuware.com/products/devpartner/profiler/default.asp?cid=701000000004ej0AAA&focus=&productfocus=&source=Web+-+Evaluation+Request&offering=DevPartner&productfamily=DevPartner&desc=The+DevPartner+Community+Profiler+Edition+is+a+product+download+that+offers+customers+and+prospects+a+high-level+view+of+the+performance+profiling+capabilities+of+DevPartner+Studio+Professional+Edition.&trk=200601-74

CLR profiler는 CLR Profiler (v1.1)
http://www.microsoft.com/downloads/details.aspx?FamilyId=86CE6052-D7F4-4AEB-9B7A-94635BEEBDDA&displaylang=en



Visual C++ 6.0
자체 프로파일러 사용

  1.. 메뉴의 Project/Setting...을 열어 Link tab에
  Enable Profiling이라는 체크박스를 체크합니다.


  2.. 프로젝트를 다시 빌드합니다.


  3.. Build 메뉴의 맨끝에 있는 Profile...을 선택합니다.


  4.. 다이얼로그에 보면 Profile Type이 몇가지 나옵니다.
  이중에 Function timing을 선택하고 OK를 누르면 실행됩니다.
  (이때, 실행파일이 있는 폴더에 *.map파일이 반드시 있어야 합니다.)


  5.. 종료후에 Output창 맨끝 tab에 있는 Profile탭을 열면 결과를 볼수
있습니다.


여기까지는 exe파일의 profiling에만 해당되는 사항입니다.
다음은 dll의 profiling방법입니다.


  1.. 위 단계의 3번까지는 dll도 똑같습니다.
  (dll과 exe모두 Enable Profiling상태로 빌드하고, exe가 ActiveProject가
되어있어야 합니다.)


  2.. 일단 아래와 같은 내용의 profdll.bat파일을 만듭니다.

  copy %1.dll save
  prep /OM %1.dll
  copy %1._ll %1.dll
  profile /I %1 /O %1 %2
  copy save %1.dll
  prep /M %1
  plist %1


  3.. command line에서 실행할 경우는 아래와 같이 실행시킵니다. (파일이름은
확장자없이)
  profdll dllfile exefile


  4.. 비주얼스튜디오내에서 실행할 경우에는
  Build/Profile...의 대화상자에서 Profile type중 custom을 선택합니다.
  그리고나서, Custom Settings에서 3번과 같이 써주면 되구요.


마지막으로, 실행을 위해서는 Build메뉴의 Profile...을 선택하면 됩니다.

아래는 profile 결과물 샘플입니다.


     Func          Func+Child          Hit
     Time   %         Time      %     Count   Function
-------------------------------------------------------
4832.446  57.5     4832.446  57.5   104418 CString::operator+=(char)
(mfc42d.dll)
  559.958   6.7      559.958   6.7      524 CDC::DrawTextA(class CString
const &,struct tagRECT *,unsigned int) (mfc42d.dll)
  184.740   2.2      196.883   2.3       38
CYWndViewer::OnUpdatePagenext(class CCmdUI *) (ywndviewer.obj)
  137.745   1.6     5059.470  60.2     1496 CYWndViewer::GetToken(unsigned
char &,class CString &) (ywndviewer.obj)
   88.514   1.1       88.514   1.1     3893 CString::~CString(void)
(mfc42d.dll)


============================================================================
===

Profiler를 이용하면 아래와 같은 재미있는 성능테스트도 할수있습니다.
아래는 '비사모'의 Visual C++ Tip/Tricks 게시판에서 퍼온 글입니다.


PERFORMANCE TESTS
COMPUTER DATA:
Processor: Pentium Pro 200
Memory: 64 MB
Software: Visual C++ 5.0
System: NT 4.0 with service pack 2

CWnd::GetDlgItem() versus ::GetDlgItem()
Using member variables in functions versus automatic variables
Decrease the number of allocations that is done in a application for CString
Using pointers to objects versus many parameters when sending data to
functions

How to improve the speed for a application depends on what type of
application you are building.
Every application usualy have some sort of core where a lot of time is
spent.
Improving speed for this core will make your whole application run faster.
When the design of a new application is started it is vital that you spend a
lot of time to try to figure out
what the applications main tasks will be (programmatically).
And that a core is built that can manage most of these tasks.
If the application don't have some sort of core.
It is either a very strange application or you have "spagetti code".
If you have "spagetti" you are in big trouble.
Lists, drawing code, memory management, database design, SQL-queries etc.
Are areas where you can gain much improvement by designing for speed.
The samples below will not make a big impact for the speed of your
application,
but it is small improvements that you might not have thought about.


Back to home

CWnd::GetDlgItem() versus ::GetDlgItem()
  When getting pointers to a controls in MFC, CWnd::GetDlgItem() is often
used.
  There is a lot of improvement to do if you are getting pointers or a
handle to different controls
  in your application by using the API ::GetDlgItem() instead of
CWnd::GetDlgItem().
  This is because MFC are storing objects for each window in a hash table
and are using the handle as a key.
  So when the CWnd::GetDlgItem() is used,
  the ::GetDlgItem() gets the handle and then then the window object is
looked up in hash table.
  If the window object is found (serious error if not !) it is returned.

----------------------------------------------------------------------------
----

void CTestDlg::GetDlgItemAPI()
{
   HWND hEdit; UINT uCounter;
   for( uCounter = 0; uCounter < 100000; uCounter++ )
   {
      hEdit = ::GetDlgItem( m_hWnd, IDC_EDIT1001 );
   }
}

void CTestDlg::GetDlgItemMFC()
{
   CEdit* pEdit; UINT uCounter;
   for( uCounter = 0; uCounter < 100000; uCounter++ )
   {
      pEdit = (CEdit*)GetDlgItem( IDC_EDIT1001 );
   }
}

void CTestDlg::OnButton1()
{
   GetDlgItemMFC();
   GetDlgItemAPI();
}

     Func       Func+Child     Hit
     Time          Time       Count     Function
---------------------------------------------------------
267.004         267.004         1    CTestDlg::GetDlgItemMFC(void)
38.205          38.205         1    CTestDlg::GetDlgItemAPI(void)


Using member variables in functions versus automatic variables
  When you are using member variables in member functions.
  There is some overhead that is done.
  The "this" pointer is loaded into one of the CPU's register before the
member is used.
  The bad thing about this is that the code gets bigger and a little slower.
  If you are using a member variable in a member function on many places or
like the sample below, in a loop.
  Then you can increase the speed and decrease the code size by assigning
automatic variables to member variables.
  Use these automatic variables in the function
  and when the function is finished assign the members to the automatic
variables.

----------------------------------------------------------------------------
----

void CTestDlg::Member()
{
   UINT uCounter;
   m_lSum = 0; m_lTemp = 0;

   for( uCounter = 0; uCounter < 1000000; uCounter++ )
   {
      m_lTemp++;
      m_lTemp++;
      m_lSum += m_lTemp;

      if( m_lSum )  m_lSum--;
   }
}

void CTestDlg::Auto()
{
   UINT uCounter; LONG lSum, lTemp;
   lSum = 0; lTemp = 0;

   for( uCounter = 0; uCounter < 1000000; uCounter++ )
   {
      lTemp++;
      lTemp++;
      lSum += m_lTemp;

      if( lSum )  lSum--;
   }

   m_lTemp = lTemp; lSum = m_lSum;
}

void CTestDlg::OnButton1()
{
   Auto();
   Member();
}

  Func      Func+Child        Hit
  Time         Time          Count  Function
---------------------------------------------------------
36.801          36.801         1    CTestDlg::Member(void)
15.071          15.071         1    CTestDlg::Auto(void)





Decrease the number of allocations that is done in a application for CString
  CString is very fast if used correctly. But you need to how it works
internally.
  When you add text to a CString and the internal buffer is to small,
  it needs to increase the buffer and copy the new text into it.
  If the buffer is large enough to fit the characters that is added, no
allocation is done.

----------------------------------------------------------------------------
----

void CTestDlg::NoPreAlloc()
{
   CString stringText;

   stringText += _T("1");
   stringText += _T("2");
   stringText += _T("3");
   stringText += _T("4");
   stringText += _T("5");
   stringText += _T("6");
   stringText += _T("7");
   stringText += _T("8");
   stringText += _T("9");
}

void CTestDlg::PreAlloc()
{
   CString stringText;

   stringText.GetBuffer( 10 );
   stringText += _T("1");
   stringText += _T("2");
   stringText += _T("3");
   stringText += _T("4");
   stringText += _T("5");
   stringText += _T("6");
   stringText += _T("7");
   stringText += _T("8");
   stringText += _T("9");
}

void CTestDlg::OnButton1()
{
   UINT uCounter;

   for( uCounter = 0; uCounter < 1000; uCounter++ )
   {
      NoPreAlloc();
      PreAlloc();
   }
}

  Func  Func+Child    Hit
  Time     Time      Count  Function
------------------------------------
31.739     31.739    1000 CTestDlg::NoPreAlloc(void)
10.370     10.370    1000 CTestDlg::PreAlloc(void)





Using pointers to objects versus many parameters when sending data to
functions
  It is best to use a pointer to an object instead of sending many
parameters.
  The gain in performance for many parameters is very small and as you can
se in the sample below,
  it is only acquired in very extreme cases.
  Most often you don't need to assign all members for the object before
calling the function.
  It is easier to modify the code if pointer to an object is sent, instead
of using a lot of parameters.
There is some places where it could be better to send many parameters
instead of pointer to an object,
one is when a object is using it's own private member functions.

----------------------------------------------------------------------------
----

struct SSDummy {int i1;int i2;int i3;int i4;int i5;int i6;int i7;};

void CTestDlg::ManyParameter( int i1,int i2,int i3,int i4,int i5,int i6,int
i7 )
{
   int iSum;
   iSum = i1 + i2 + i3 + i4 + i5 + i6 + i7;
}

void CTestDlg::OneParameter( SSDummy* pDummy )
{
   int iSum;
   iSum = pDummy->i1 + pDummy->i2 + pDummy->i3 +
          pDummy->i4 + pDummy->i5 + pDummy->i6 + pDummy->i7;
}

void CTestDlg::Many()
{
   int i1; int i2; int i3; int i4; int i5; int i6; int i7;
   i1 = 0; i2 = 0; i3 = 0; i4 = 0; i5 = 0; i6 = 0; i7 = 0;

   ManyParameter( i1, i2, i3, i4, i5, i6, i7 );
}

void CTestDlg::One()
{
   SSDummy Dummy;
   Dummy.i1 = 0; Dummy.i2 = 0; Dummy.i3 = 0; Dummy.i4 = 0;
   Dummy.i5 = 0; Dummy.i6 = 0; Dummy.i7 = 0;
   OneParameter( &Dummy );
}

void CTestDlg::OnButton1()
{
   UINT uCounter;

   for( uCounter = 0; uCounter < 100000; uCounter++ )
   {
      Many();
      One();
   }
}

  Func Func+Child    Hit
  Time    Time      Count  Function
------------------------------------
30.230    37.922   100000  CTestDlg::One(void)
19.668    24.565   100000  CTestDlg::Many(void)
7.693     7.693   100000  CTestDlg::OneParameter(struct SSDummy *)
4.897     4.897   100000
CTestDlg::ManyParameter(int,int,int,int,int,int,int)

'KB > C/C++' 카테고리의 다른 글

cl.exe Episode XIII: Attack of the Standards: VC6, 7에서 C++ 표준 적용 사항  (0) 2006.06.28
typeof  (0) 2006.06.28
code profiler  (0) 2006.04.17
함수 링크 순서 정해주기  (0) 2005.10.28
RSA를 이해하기 위한 코드  (0) 2005.03.25
[펌] vc 5, 6 stl 버그 픽스  (0) 2004.09.10
YOUR COMMENT IS THE CRITICAL SUCCESS FACTOR FOR THE QUALITY OF BLOG POST


함수 링크 순서 정해주기
오후 12:48 2005-10-28 조경민 bro@shinbiro.com
========================================================

vc linker 옵션중 /ORDER 옵션으로 링크시 함수 순서를 결정해줄 수 있다.
문법
  /ORDER:@filename

링크된 함수 순서는 링크시 /map 옵션을 주어 map file을 생성하게 해서
알 수 있다.

1. Project/Settings/C&C++ 에서 /Gy 옵션을 추가한다.
2. func.txt 파일을 만든다. 파일 안에 순서대로 링크할 함수들을 추가한다.

만일 start라는 함수를 처음 링크하고자 할때 func.txt 안 내용

start

3. Project/Settings/link 에서 /ORDER:@func.txt 와 /MAP (또는 Generate Map File선택)을 추가

컴파일해본다.
맵파일을 보면 링크 순서가 바뀌어 실제 가상주소상 위로 올라옴을 알 수 있다.(Rva+Base)
원래는
  Address         Publics by Value              Rva+Base     Lib:Object

0001:00000000       _int0                      00010400     intasm.obj
0001:0000000e       _jump_to                   0001040e     intasm.obj
0001:00000020       _start                     00010420 f   _main.obj
     :
이었는데, 아래처럼 바뀐다.

  Address         Publics by Value              Rva+Base     Lib:Object

0001:00000000       _start                     00010400 f   _main.obj    <- 처음으로 올라왔다.
0001:000000e0       _int0                      000104e0     intasm.obj
0001:000000ee       _jump_to                   000104ee     intasm.obj
     :

'KB > C/C++' 카테고리의 다른 글

typeof  (0) 2006.06.28
code profiler  (0) 2006.04.17
함수 링크 순서 정해주기  (0) 2005.10.28
RSA를 이해하기 위한 코드  (0) 2005.03.25
[펌] vc 5, 6 stl 버그 픽스  (0) 2004.09.10
[펌] C++ Reverse Disassembly  (0) 2004.09.10
YOUR COMMENT IS THE CRITICAL SUCCESS FACTOR FOR THE QUALITY OF BLOG POST


// MiniiRSA.cpp : 콘솔 응용 프로그램에 대한 진입점을 정의합니다.
//

#include "stdafx.h"
#include <stdio.h>
#include <conio.h>

/*

2005/03/25 bro 조경민 (bro@shinbiro.com)
RSA Algorithm For understanding
===================================================
목적 : 간단한 상황을 만들어 RSA 알고리즘을 이해
용어 : RSA - 정수론을 이용하여 만든 공개키 알고리즘
       공개키 알고리즘 - 데이터를 보낼 때 상대방의 공개키로 암호화 하여
                             보내면 상대방은 암호문을 자신이 갖고있는 개인키로
                                                 복호화하여 데이터를 받을 수 있는 알고리즘
       공개키 - 암호화하는 키로 평문(Plain Text)를 암호문(Cipher)로 만듬
           개인키 - 보곻화하는 키 또는 비밀키로 암호문을 평문으로 만듬
           ----------------------------------------------
기본지식 : 정수론
           약수 - 어떤 수가 작은수의 곱으로 표현될때 이 작은수를 약수라함
                  Ex) 12 = 1,2,3,4,6,12 는 약수
       공약수 - 두 수의 약수중 서로 같은 약수
                  Ex) 12 = 1,2,3,4,6,12    8=1,2,4,8 일때 공약수 1,2,4
           최대공약수 - 두 수의 약수중 가장큰 약수gcd로 표현 gcd(12,8) = 4
           유클리드 호제법 - 최대공약수를 구하는 방식 gcd(큰수,작은수) = gcd(작은수,큰수/작은수의 나머지)
                             gcd(100,86) = gcd(86,14) = gcd(14,4) = gcd(4,1) 이므로 최대공약수는 4
           서로소 - 서로 공약수가 1밖에 없음 Ex) 23, 11은 서로소
       ----------------------------------------------

          
설명 :
       임의의 두 소수 p와 q가 있을때
           p * q = N
           ( p - 1 ) * ( q - 1 ) = z
           이 때, z와 E는 서로소이며  E < z 여야 함

           공개키는 (N,E)

           E와 D를 곱한 것을 z로 나눈 나머지가 1일 때
       E * D = 1 ( mod z )

           개인키는 D

상황 : 키와 plain 은 모두 작은 값이다.
       plain은 N을 넘을 수 없다.

개선사항 : Big Number지원
           소수 찾기 알고리즘
           알고리즘 최저화
*/

// 최대공약수를 구하는 유클리드 호제법
// gcd(100,86) = gcd(86,14) = gcd(14,2) = gcd(2,1)
// 리턴이 1이면 서로소
int gcd(int max, int min)
{
        if( min == 0 )
                return max;
        else        
                return gcd( min, max%min );
}


// 서로소인 수를 찾는 함수
// 최대공약수가 1이면 서로소이다.
int disjoint( int z, int _E = 2 )
{
        int E;
        for( E = _E; E < z; E++ )
        {
                if( gcd( z, E ) == 1 )
                        return E;
        }
        return 0;
}

// 공개키 (pN, pE) 개인키 (pD) 를 찾는 함수
// 초기 소수 p와 q는 입력해주어야 한다. (개선의 여지가 있음)
int get_keys( int p, int q, int* pN, int* pE, int* pD )
{
        int N,z,E,D;
        
        // 먼저 N, z, E를 마련한다.
        N = p*q;
        z = (p-1)*(q-1);
        // 공개키를 구하자.
        // E는 z보다 작은 서로소이다.
        E = disjoint( z );

        // 개인키를 구하자.

        // E*D = 1 ( mod z )
        // E*D/z 로 나눈 나머지는 1
        while( E > 0 && E < z )
        {
                // 공식을 만족하는 개인키 D를 계속 찾아본다.
                for( D = 2; D < z ; D++ )
                {
                        if( (E*D)%z == 1 )
                        {
                                // 개인키를 찾았다.
                                *pN = N;
                                *pE = E;
                                *pD = D;
                                return 1;
                        }
                }

                // z와 다음 서로소를 구한다.
                E = disjoint( z, E+1 );
        }
        return 0;
}


// plain과 공개키 (N,E)로 암호화 하는 함수
// plain을 E번 곱하되, 곱한 중간 값이 N을 넘으면
// N으로 나눈 나머지로 만들어준다. ( N으로 계속 빼주는 방식도 된다)
int encrypt( int plain, int N, int E )
{
        int enc = 1;
        for( int i = 0 ; i < E; i ++ )
        {
                enc = enc*plain;
                if( enc > N )
                        enc = enc % N;
        }
        return enc;
}

// 암호문과 개인키 (N,D)로 암호를 푸는 함수
// encrypt와 동일하다.
int decrypt( int enc, int N, int D )
{
        int plain = 1;
        for( int i = 0 ; i < D; i ++ )
        {
                plain = plain*enc;
                if( plain > N )
                        plain = plain % N;
        }
        return plain;
}


int _tmain(int argc, _TCHAR* argv[])
{
        printf("100과 84의 최대공약수 = %d \r\n", gcd( 100, 84) );
        printf( "24 와 서로소인 수는 = %d \r\n" , disjoint( 24 ) );

        int N,E,D;
        get_keys( 5,7, &N, &E, &D );

        printf( "p=5, q=7 의 공개키(N,E)=(%d,%d) 비밀키D=%d \r\n", N, E, D );

        int plain = 13;
        int enc = encrypt( plain, N, E );
        int dec = decrypt( enc, N, D );
        printf( " plain = %d   encrypt(plain,N,E) = %d , decrypt(enc,N,D) = %d \r\n" , plain, enc, dec );
        getch();
        return 0;
}

------------------------------------------------------------------
네이버 지식인 발췌


정수론이 발달함에 의해서 혁신 적인 보안 시스템이 만들어 졌죠.. DES 시스템의 단점을 보완한 공개키 시스템 RSA는 상당히 큰 정수의 소인수분해가 힘들다는 점을 이용해 만들었습니다. R. Rivest, A. Shamir, L. Adleman 의 첫 글자를 따서 붙였다고 배웠습니다. 오일러 파이함수나, 일차 합동식, 유클리드 알고리듬 정도는 이해 하셔야 할 것입니다.

1) 적당히 비슷하고 큰 소수 p, q를 구합니다.
2) 공개키 n을 생성합니다. (n=pq)
3) φ를 구합니다. φ = (p-1)(q-1)
4) 최대공약수 gcd(s,φ)=1을 만족하는 즉 서로 소인 또다른 공개키 s를 생성합니다. 1< s < φ
5) 유클리드 알고리듬을 이용하여 비밀키 d를 만듭니다. d = s^-1 (mod φ) (sd≡1 (mod φ) 를 구하는 것이지요. 무엇을 선택하든 상관없습니다.) 를 구하는 것이지요. 1< d < φ
※ 확장된 유클리드 알고리듬으로 정수 d를 구하는 법
t_0 = 0
t_1 = 1
t_j = t_(j-2)-q_(j-1)t_(j-1) mod r_0 (단, j≥2)
위 방법을 이용하여 d를 구한다.

암호화) n보다 작은 수로 메세지 M을 정한 다음,암호문 c = M^s (mod n) 을 계산하여 암호문 c를 보낸다.
복호화) M = c^d (mod n)을 사용해 복호한다.

이렇게 쓰기만 하면 잘 모르니, 예를 들어보지요.
1) 소수 5와 7을 골랐습니다.
2) 공개키 n=35를 만들었지요.
3) φ=24를 구했습니다.
4) 24와 서로소인 11=s를 구했습니다.
5) 현재 공개키 (n,s) = (35,11)을 구했지요
6) 비밀키 d를 구합니다.
d = 11^-1 (mod 24)
확장된 유클리드 알고리듬의 적용.
11^-1 (mod 24) --- 주어진 식

24 = 2*11+2(=r1)
--- 이것은 이해 하죠? 24(=n)를 앞의 11(=s)로 나누어 몫과 나머지 형태로 나타낸 것입니다. n = q(=몫)*s+r1(=나머지1)

(t_2)0-2*1 (mod 24) = -2 (mod 24) = 22(=r2) (mod 24)
--- 여기도 쉽습니다.t_(2-2)=0이므로 0-2(=q)*1(t_(2-1)=1) (mod 24) = -2 (mod 24) = 24-2 (mod 24) = 22 (mod 24)

11 = 5(=q2)*2(r1)+1(r3)
---s를 앞에서 나온 나머지 r1으로 나눈 것이죠. 검산식 형태.. (현재 여기서는 나머지가 1이 나왔기 때문에 유클리드 알고리듬은 끝이 난 것입니다.)

(t_3)1-22*5 (mod 24) = -109 (mod 24) = 11 (mod 24)
--- 1(=t_(3-2)) - 22(r2)*5(q2) (mod 24) = -109 (mod 24) = 24*5-109 (mod 24)=11(mod 24)

따라서 d = 11.

암호화) 메세지 3을 암호화 해본다. 암호문 c = 3^11 (mod 35) = 12
복호화) 암호문 12를 복호화 해본다. 메세지 M = 12^11 (mod 35) = 3.
복호화가 제대로 되었죠.. 확장된 유클리드 알고리듬을 적용할 때, 나머지가 1이 나올 때까지 계속 반복하시면 됩니다.
죄송합니다.암호화 된 것이 복호화 되는 과정의 증명까지는 지금 시간이 다되서 다 못쓰겠네요. 도움이 되셨기를..
(φ는 사실 φ(n)을 뜻하는 오일러 함수 값입니다.)
(http://203.253.25.15/~mhkim/c200012/rsa.ppt 를 가보면 설명이 자세히는 되지 않았지만 많은 예를 볼 수 있습니다.)



-----------------------------------------------------------------------


서로소 [relatively prime/disjoint]  
  




요약
1 이외에 공약수를 갖지 않는 두 자연수.







본문
예를 들면 두 자연수 4와 9는 서로소이다. 즉 4의 약수는 1, 2, 4이고 9의 약수는 1, 3, 9이므로 두 수의 공약수는 1밖에 없다. 마찬가지로 7과 13, 또는 20과 21, 또는 33과 98 등이 서로소이다. 두 수가 서로소인가를 알아보는 데에는 유클리드의 계산법을 많이 사용한다. 일반적으로 두 다항식 f(x)와 g(x)가 공통인수를 갖고 있지 않을 때 f(x)와 g(x)는 서로소라고 한다. 또 두 집합 A와 B에 공통으로 속하는 원소가 없을 때, 즉 A∩B=Ø일 때 집합 A와 B는 서로소라고 한다. 예를 들어 A={1, 2, 3}이고 B={4, 5}일 때 A와 B는 서로소이다. 이것을 벤다이어그램으로 나타내면 집합 A와 B가 서로 겹치는 부분이 없이 떨어져 있다.


----------------------------------------------------------------------

유클리드 호제법은 최대공약수를 구할때 사용합니다.

A,B의 최대공약수를 G라 할때
A=Ga, B=Gb(a,b는 서로소)로 나타낼 수 있습니다.

A=BQ+R에 A=Ga, B=Gb를 대입하면
Ga=GbQ+R
R=G(a-bQ)인데
a-bQ와 Gb는 서로소이므로(왜냐면 a,b가 서로소이므로)
B와R의 최대공약수도 G가 나옵니다.

요약하자면
A와B의 최대공약수가 B와 R(A를B로 나눈 나머지)의 최대공약수와 같다는것입니다.

--------------------------------------------------------------------------
최대공약수 [最大公約數, greatest common measure]  
  




요약
2개 이상의 수의 공약수 중에서 최대인 것.







본문
이를테면, 18의 약수는 1, 2, 3, 6, 9, 18 12의 약수는 1, 2, 3, 4, 6, 12 로서 6이 최대공약수이며, 이것을 (12,18)=6으로 쓴다. 다른 공약수는 모두 6의 약수이다, 최대공약수를 구하는 방법은, 우선 소인수(素因數)로 분해하여 공통의 수를 택하여 곱해주면 된다. 예를 들면 (12,18)을 구할 경우 12=2×3, 18=2×3이므로 (12,18)=2×3=6이 된다. 또, 주어진 수가 커서소인수분해하기 곤란할 때에는 유클리드의 호제법을 이용하는 것이 더 간편하다.

두 수 A,B의 최대공약수를 G, 또 A,B를 각각 G로 나누었을 때의 몫을 a,b라 하면, A=aG, B=bG인 관계가 성립한다. 이 때 a, b는 서로 소(素), 즉 (a,b)=1이다. 또 A,B의 최소공배수가 L이면, LG=AB인 관계가 성립한다. 세 수의 경우 (A,B,C)=((A,B),C), 즉 두 수의 최대공약수와 나머지 한 수의 최대공약수를 구하면 결국 세 수의 최대공약수가 된다. 네 수 이상에서도 마찬가지로 생각할 수가 있으며, 최소공배수에서도 [A,B,C]=[[A,B],C]가 성립한다.

----------------------------------------------------------------------------
소인수 [素因數, prime factor]  
  




요약
인수 중에서 소수(素數)인 것.







본문
예컨대, 12의 약수 1, 2, 3, 4, 6, 12 중에서 2와 3은 소수이지만, 1, 4, 6, 12는 소수가 아니다. 따라서 12의 소인수는 2와 3이다.






----------------------------------------------------------------------------
약수 [約數, divisor]  
  




요약
어떤 수를 나누어 떨어지게 할 수 있는 수.







본문
즉 정수(整數) a가 둘 이상의 정수의 곱으로 표시되어 a=b ·c ·d ·…가 될 때 b,c,d,…를 각각 a의 약수 또는 인수(因數)라 한다. 이것에 대하여 a를 b,c,d,… 등의 배수라고 한다. 예를 들면, 12=1×2×6=4×3이므로 1,2,3,4,6,12는 각각 12의 약수이고, 또 12는 1,2,3,4,6,12의 각각의 배수이다.

0이 아닌 수의 배수는 무수히 많으며, 약수는 한정되어 있고, 0은 모든 수의 배수이나 어떤 수의 약수는 되지 않는다. 0이 아닌 수는 그 수 자신의 배수인 동시에 약수도 된다. 또, 다항식(多項式) f(x)도 f(x)=h(x) ·g(x) · …와 같이 둘 이상의 식으로 분해가 될 때 h(x), g(x) 등을 각각 f(x)의 약수 또는 인수라 한다. 예를 들면, (x+1)(x+2)는 x(x+1)(x+2)2의 약수 또는 인수이다.


------------------------------------------------------------------------
공약수 [公約數, common divisor]  
  




요약
2개 이상의 정수, 또는 다항식에 공통인 약수.







본문

즉, 정수 m이 2s 이상의 정수 a1,a2,a3,…,as의 각각의 약수가 될 때, 이를 m을 a1,a2,a3,…,as의 공약수라 한다.

이를테면, 6은 3개의 정수 24,36,60의 공약수이다. 또, 18의 약수는 1,2,3,6,9,18이며, 12의 약수는 1,2,3,4,6,12이다. 이 중에서 공통인 약수는 1,2,3,6이므로 1,2,3,6은 18과 12의 공약수이다.

공약수 중에서 가장 큰 공약수를 최대공약수라 하고, 보통 G.C.M.으로 나타낸다. m이 a1,a2,a3,…,as의 공약수이면, m의 약수 역시 a1,a2,a3,…,as의 공약수이다. 다항식에서도 정수에서와 마찬가지로 공약수라는 말을 쓴다.

즉, 변수 a1,a2,a3,…,as의 다항식 f(x1,x2,…,xn)가 2개 이상의 다항식 g1(x1,x2,…xn),…, gs(x1,x2,…,xn)의 각각을 나누어 떨어지게


-----------------------------------------------------------------------
[답변] 유클리드 호제법에 관하여... 푸른하늘
휴............

또 요즘 내 주는 수행평가가 그런 건가보죠?

아니면, 한 분이 계속 이름 바꿔가며 올리시는 건???!!! ^.^

농담이구요, 암튼, 너무 많은 분이 올리시네엽. 수행평가마저도 획일적 교육이 되다니...

유클리드 호제법에 관해 간단히 설명드리겠습니다.

목적은 두 수의 최대공약수를 찾아내는 겁니다. 계산이 여러분이 이미 배운 최대공약수 구하는 방법에 비해 그렇게 효율적이지는 않지만, 단순한 계산의 반복이기 때문에 컴퓨터에서 잘 사용되는 알고리즘이기도 합니다.

원리는 다음과 같습니다.
A=BQ + R 의 관계가 성립할 때
A와 B의 최대공약수는 B와 R과의 최대공약수와 같다는 원리입니다. 한 번 증명해 보겠습니다.

A와 B의 최대공약수를 G라고 하면 각각 A=aG, B=bG (단, a, b는 서로 소)라고 쓸 수 있습니다. 그러면 위의 식은 다음과 같이 됩니다.
aG = bGQ + R
(a-bQ)G = R

좌, 우변 모두 정수이므로, R은 G의 약수여야 합니다. 이상으로 증명이 끝났습니다.

계산법은 뭐냐면요, 뭐, 위의 원리를 그대로 쓰는 거지만... 두 수의 최대공약수를 구할 때, 작은 수와, 나머지와의 최대공약수를 구한다고 생각하시면 됩니다. 음... 100과 60의 최대공약수를 유클리드 호제법으로 구하면,

100 = 60 * 1 + 20 이니까 (60, 20)을 생각해보면 됩니다.

60 = 20 * 3 이므로 최대공약수는 20이 됩니다.

우.... 너무 쉬운 예를 들어서... 다른 거 하나 더 해볼까요? 100하고... 84로 해 볼까요?

100 = 84 * 1 + 16 --- (100,84) = (84,16)
84 = 16 * 5 + 4 ----- (84, 16) = (16, 4)
16 = 4 * 4

그러므로 (100, 84) = 4가 되겠군요.

유클리드 호제법은 단순한 계산 방법으로 인해, 단순히 두 수만이 아니라 두 다항식의 최대공약수를 구하는데도 강력한 힘을 발휘합니다.

--------------------------------------------------------
http://blog.naver.com/muse1472/120010861477


내 블로그에 담기
카페에 담기

프린트 하기

스크랩 : 금지됨
카페에 담기
오픈사전에 등록

프린트 하기

스크랩 : 금지됨
카페에 담기

프린트 하기

      
목록보기 | 컴관련__________▣ (62)  스크랩 엮인글 목록열기 ▼ 목록닫기 ▲  






RSA 알고리즘 개요 | ▣ 컴 관련 2005/03/07 09:42  

http://blog.naver.com/muse1472/120010861477



인터넷과 암호

  컴퓨터에 조금만 관심이 있는 사람이면 누구나 인터넷으로 오고가는 각종 정보에 암호가 사용되고 있다는 것을 알고 있습니다. 인터넷 세계를 열심히 서핑하는 사람이라면 어쩌면 PGP(Pretty Good Privacy)라는 암호 프로그램을 알고 있을지 모릅니다.
  




  좀 더 관심이 있는 사람이라면 PGP의 암호화 알고리즘이 전자상거래, 금융, 전자서명 등의 보안에 사용되고 있는  RSA라는 수학적 알고리즘이라는 것까지도 알고 있을 것입니다. 그러나 수학이나 암호에 전문적인 지식이 없다면 그 RSA에 의한 암호화와 복호의 비밀을 알고 있는 사람은 아마도 흔치 않을 것입니다. RSA가 대체 무엇이며, 왜 그것이 마법의 암호라고 불리울까? 이 글은 이러한 궁금증에 대한 초보적인 대답을 드림으로써 아마추어의 지적 호기심에 부응하고자 하는 목적에서 작성하였습니다.



  잠그는 열쇠와 여는 열쇠가 다른 암호


  암호화(encoding, enciphering, cryptography, encryption)는 흔히 자물쇠를 채우는 행위, 반대로 복호(decoding, decryption)는 자물쇠를 여는 행위에 비유되곤 합니다. 이 때문에 암호화와 복호에 사용되는 수단을 key라고 부르고, 그것이 문장이나 숫자인 경우에는 keyword라고 부릅니다. 우리가 "종합판례정보시스템"에서 검색용으로 사용하는 주제어를 의미하는 keyword와는 물론 다른 의미의 keyword입니다.

  1976년 어쩌면 1978년 이전까지 암호화의 key와 복호의 key는 항상 동일한 것이었습니다.복호 작업은 언제나 암호화 작업을 반대방향으로 되풀이하는 것이기 때문에 복호를 위해서는 반드시 암호화에 사용된 key와 동일한 key가 필요하고 이것이 보통사람들의 상식에 부합하는 것입니다.

  그런데 만일 잠그는 key와 여는 key가 다르다면, 잠그는 key로 암호화하고 나면 그 key로는 복호할 수 없고 반드시 또 다른 key가 있어야만 열 수 있다면 무척 편리할 것입니다. 여러분은 그 여는 key를 일반에 공개하고 여러분에게 보내는 편지를 그 공개 key로 암호화할 것을 요구할 수 있을 것입니다. 일단 암호화된 편지는 여는 key를 갖고 있는 당신 외에는 이 세상 누구도, 심지어는 그 암호문을 작성한 사람까지도 열어 볼 수 없을 것입니다.


  또 이런 경우도 있을 수 있습니다. 먼저 A회사가 많은 고객의 신용정보(예컨대 비밀번호)를 보관하고 있다고 가정해 봅시다. A회사의 컴퓨터 어딘가에는 그 많은 고객들의 신용정보가 들어 있을 것이고, 그 정보가 유출될 경우 A회사는 엄청난 손해배상책임을 부담하게 될 위험성이 있습니다. 그래서 A회사는 이 평문(plain text, 암호화하기 전의 자료를 지칭합니다)으로 된 신용정보를 암호화하여 저장한 후 평문을 폐기하기로 결정하였습니다. 그런데 문제가 생겼습니다. 암호화와 복호 작업을 위하여 key를 컴퓨터 어딘가에 보관해 두어야겠는데 그 key가 암호화된 정보와 함께 유출되면 역시 엄청난 손해배상책임을 부담하게 될 것이기 때문입니다.


  결국 A회사는 다음과 같은 보안 시스템을 생각해 내었습니다. 고객과 거래를 시작할 때 잠그는 key와 여는 key를 만들어 여는 key를 고객의 카드에 기록하고, 회사의 컴퓨터에는 잠그는 key와 그 key로 암호화된 정보만을 기록해 두기로 하였습니다(평문 정보는 고객의 머리에 기록되어 있습니다). 이렇게 되면 암호화 작업이 끝난 후에는 A회사 스스로도 평문 정보를 알 수 없게 되기 때문에 암호화된 정보와 잠그는 key가 사고로 유출되더라도 고객들에게 피해를 줄 염려가 없게 됩니다.



  그런 후에 인출작업의 순서는 다음과 같습니다. 고객이 A회사의 단말기에 카드를 삽입하고 keybord를 이용하여 평문 정보를 입력하면 단말기는 주(main) 컴퓨터로부터 암호화된 고객의 정보를 제공받고 고객의 카드로부터는 고객의 여는 key를 제공받아 이 key를 사용하여 암호화된 고객 정보를 평문 정보로 복호한 후 고객이 입력한 평문 정보와 비교합니다. 이것이 일치하면 인출을 승인하고 이것이 불일치하면 인출을 거부하게 됩니다. 이제 A회사는 여는 key와 평문정보 어느 것도 보관하지 않으면서 고객의 신분을 확인할 수 있게 되었습니다.



  물론 고객이 카드와 비밀번호를 함께 분실한다면 고객에게 손해가 발생하겠지만, 첫째 이는 고객의 잘못으로 인한 것이기 때문에 손해배상책임을 부담하지 않을 것이고, 둘째 설사 책임을 부담한다고 하더라도 이는 대규모 정보유출에 비하면 극히 작은 손해이므로 직접 부담하거나 보험에 의하여 보장받을 수 있습니다. 이러한 보안 시스템은 이미 만들어져 있고 멀지 않은 장래에 IC카드의 보급과 함께 실용화될 것으로 예상됩니다. 어쩌면 이미 실용화되었는지도 모릅니다.


   이러한 암호체계가 실제로 가능할까요? 개념상으로야 이러한 암호체계의 가능성이 오래 전부터 제기되어 왔고, 1976년 Diffie와 Hellman에 의하여 공개 key 개념이 제안되기는 하였지만, 실용화할 수 있는 최초의 암호 알고리즘은 1978년 MIT 공대 연구팀 소속의 세 학자 Rivest, Shamir, Adleman이 개발한 RSA입니다.



  마법의 수 트리플


  RSA를 이해하기 위해서는 먼저 RSA가 key로 사용하는 "마법의 수 트리플"를 만드는 방법을 알아야 합니다.

① 먼저 소수(素數, prime number) 2개를 선택하여 p와 q라고 합니다.

② p × q = N의 방법으로 N을 구합니다.

③ (p-1) × (q-1) = z의 방법으로 z를 구합니다.

④ z와 공약수를 갖지 않는 수 하나를 선택하여 E라고 이름짓습니다.

   통상의 계산의 편의를 위하여 z보다 작은 수 중 소수 하나를 선택합니다. E는 공개 key(잠그는 key)가 됩니다.

⑤ 비밀 key(여는 key)를 구하는 방법은 조금 까다로운데, 비밀 key를 D라고 할 때 D는 D × E / z의 계산에서 나머지가 1이 남아야 한다.

  즉, E × D ≡ 1(mod z)을 충족하여야 합니다.

  이 방법에 의하여 공개 key N과 E, 그리고 비밀 key D가 모두 완성이 되었습니다.


  다음으로 이 공개 key N과 E를 사용하여 암호화하는 방법은 다음과 같습니다.

① 먼저 평문을 수학계산을 수행할 수 있는 수(number)로 변환하여야 하는데, 컴퓨터에서는 이미 모든 문자와 기호를 수로 변환하여 사용하기 때문에 특별한 작업을 요하지 않습니다.

② 평문숫자를 E번 곱하는데 그 과정에서 나오는 중간 수가 N보다 크면 그 중간 수에서 N을 뺍니다. 그 수가 N보다 크면 몇 번이고 뺄셈을 반복하여 N을 뺍니다. N보다 작은 수가 나오면 이를 다시 평문숫자와 곱합니다. 위 작업을 반복하면 그 결과 N보다 작은 수가 남게 되는데 이것이 암호숫자입니다.

③ 위 ②의 계산결과는 또 다른 방법으로 구할 수 있습니다. 평문숫자를 E번 곱한 다음 N으로 나누면 딱 떨어지지 않고 나머지가 남게 되는데 그 나머지가 바로 암호숫자입니다. 공개 key가 작은 수일 경우에는 ③의 방법이 계산하기 쉽지만 큰 수인 경우에는 ③의 방법으로는 계산이 불가능하고 ②의 방법으로 계산하여야 합니다.
  실제 공개 key로는 1억 단위 이상의 수가 계산되는데 ③의 방법으로 이러한 계산을 수행할 수 있는 컴퓨터는 없습니다. 위 ②와 ③의 계산결과가 동일하다는 것은 여러분 각자 증명해 보십시오. 시간을 좀 걸리겠지만 이 글을 읽으시는 분들 정도의 실력이라면 증명할 수 있을 것입니다.

  이제 위와 같은 방법으로 만들어진 암호숫자를 공개 key N과 E를 사용하여 평문숫자로 복호할 수 있는지를 생각해 보십시오. 잠시만 생각해 보아도 이것이 불가능하다는 것을 알 수 있습니다.


  위 암호숫자를 평문숫자로 복호하기 위해서는 비밀 key D가 필요합니다. 그 복호의 과정은 다음과 같습니다.

① 암호숫자를 D번 곱하는데 한번 곱할 때마다 그 중간수에서 N을 뺍니다. N을 뺀 수가 N보다 크면 그 숫자가 N보다 작아질 때까지 N을 뺍니다.

② 그 중간수가 N보다 작아지면 다시 암호숫자를 곱하고, 이런 계산 방법을 D번 되풀이합니다. 그 결과 N보다 작은 수가 나오는데 그 수가 바로 평문숫자입니다.


  이제 여러분은 마법의 수 트리플을 만드는 방법과 그 수를 key로 사용하는 RSA의 연산방법을 알게 되었습니다. 이 시점에서 여러분은 당연히 이러한 의문을 갖게 될 것입니다. 위 연산을 시작하기 전의 평문숫자와 위 암호화와 복호 연산 결과 얻은 숫자가 과연 항상 동일한 숫자일까? 이 의문에 대한 가장 적절한 대답은 위 RSA 연산 값이 참임에 대한 수학적 증명일 것입니다. 그 증명은 너무나도 어렵고 복잡하여 아마추어로서는 이해하기 어려울 뿐만 아니라 증명과정만 하나의 논문 분량이 되므로 이 곳에 소개할 수가 없습니다. 솔직히 말씀드리면 저도 잘 모릅니다.



  진짜 비밀은 소수(prime number)의 성질


  여러분의 또 다른 의문은 과연 공개 key인 N과 E만으로 암호숫자를 평문숫자로 복호할 수 없는가 하는 것과 N과 E만으로 비밀 key인 D를 알 수 없는가 하는 것일 것입니다.


  먼저 첫째 의문은 위에서도 말했다시피 조금만 생각해 보면 금방 그 답이 나옵니다. 암호화 연산을 역산하기 위해서는 암호숫자에 N을 더해야 하는데 당장 처음부터 몇 번을 더해야 할지 알 수 없기 때문에 그 역산은 불가능해집니다. 즉 하나의 해답이 아니라 무한한 경우의 수가 역산으로 도출될 수 있기 때문에 이 연산은 이론적으로도 불가능하다고 할 수 있습니다.


  두 번째 의문에 대한 답은 조금 어려워집니다. 가장 타당한 답은 yes and no인데, 이론적으로는 yes(알 수 있다)이고, 현실적으로는 no(불가능하다)라는 의미입니다. 마법의 수 트리플은 일정한 법칙에 의하여 만들어지고 먼저 N과 E가 정해진 후에는 간단한 연산에 의하여 D 값이 쉽게 구해지게 됩니다. 그런데 D 값은 N과 E로부터 곧바로 구해지는 것이 아니라 N의 약수인 p와 q로 결정되기 때문에 p와 q 값을 먼저 알아야만 D 값을 구할 수 있습니다. 어려움은 여기에 있습니다. p와 q는 소수이고 N = p × q인데 아직 우리는 소수에 일반적인 규칙을 알지 못합니다. 대부분의 수학자들은 소수에는 일반적인 규칙이 없을 것으로 생각하기도 합니다.


  물론 소수의 규칙과 관련하여 몇 가지 성질이 관찰된 바는 있습니다.
  첫째 쌍둥이 소수(prime number twins)라는 것이 있는데 어떤 소수에 2를 더한 수가 역시 소수인 쌍을 말합니다. 예를 들면, 2/3으로부터 시작해서 9,900,0641/9,900,0643과 같은 숫자의 쌍을 말합니다. 수학자들은 그 쌍둥이 수의 개수가 무한할 것으로 추측하는데 아직 이를 증명한 사람은 없습니다.

  둘째 "2보다 큰 모든 짝수는 두 소수의 합이다"라는 Christian von Goldbach의 가정(假定, 또는 추측, 수학에서 참임이 증명되지 않았지만 거짓임이 밝혀지지도 않은 명제를 말합니다)이 있는데 이 역시 아직은 증명되지 않았습니다.

  셋째, 정수론(number theory) 중 가장 놀라운 정리 중 하나로 꼽히는 소수정리(prime number theorem)가 있습니다. 이 글에서 수학공식을 입력하기가 어려워 소수정리의 내용을 설명하기는 어렵지만, 이 정리 또한 연역적 방식으로 증명된 것은 아니고 컴퓨터에 의한 연산을 통하여 증명되었기 때문에 이 또한 엄격한 의미에서 증명되었다고 할 수는 없습니다(물론 컴퓨터에 의한 증명도 인정하여야 한다는 반대 견해도 있습니다).


  이 중 어느 하나만 증명하여도 평생 판결 작성으로 얻을 수 있는 것보다 더 큰 명성을 얻을 수 있고, 전 세계가 인정하는 천재의 대열에 끼어들 수 있습니다. 여러분은 한 번 도전해 볼 생각이 없으신지?


  이야기가 엉뚱한 방향으로 흘렀습니다. 각설하고 본론으로 돌아가면, 아주 큰 수의 소수를 구하는 방법은 2부터 시작하여 알려진 모든 소수로 일일이 나누기 계산을 해 보는 방법 외에는 다른 방법이 없습니다. 타원함수를 응용한 계산방법 등이 개발되었으나 아직은 가장 단순한 나누기 계산보다 더 효율적인 계산방법은 발견되지 않고 있습니다.


  따라서 아주 큰 소수인 p와 q를 곱하여 더 큰 수 N을 구할 경우 그 N의 약수 p와 q를 알아내는 방법은 역시 2부터 시작한 모든 소수로 실제 나누기 계산을 해 보는 방법밖에 없습니다. N이 50자리만 되면 약 140억번의 계산을 수행하여야 p와 q를 찾아낼 수 있습니다. RSA가 발표된 1978년경의 컴퓨터로는 200자리의 N에서 p와 q를 찾아내기 위해서는 지구의 나이만큼(약 45억년)의 시간이 필요하다고 합니다. 그렇다면 현실적으로 그 계산은 불가능하고 p와 q의 값을 모르는 이상 공개 key D 값도 알 수 없다는 결론을 내릴 수 있습니다.


  조금만 더 전문적으로 들어가 보겠습니다. 두 소수의 곱으로 만들어지는 N에 문제가 전혀 없는 것은 아닙니다. 1977년 8월 3명의 수학자가 Scientific American(이 잡지는 영국의 Nature와 더불어 세계에서 가장 유명한 과학전문잡지입니다. http://www.sciam.com/를 찾아가시면 놀라운 지식의 보고를 접하게 됩니다.)에 두 소수의 곱으로 만들어진 129자리의 수를 올려놓고 이 수의 소인수 분해에 100달러의 상금을 걸었습니다. 출제자는 아마도 이 문제를 푸는 사람이 없을 것이라고 확신하였을 것입니다. 그런데 5년 후 1992년 4명의 수학자가 전세계 25개국의 자원봉사자 600명을 모집한 후 인터넷을 통하여 공동작업을 벌인 결과 64자리 수의 소인수를 찾아내고 말았습니다. 참여자들에게 돌아간 상금은 1인당 17센트였다고 합니다.


  그런데 같은 해에 Lester와 Bernstein이라는 사람이 단 한 대의 컴퓨터로 3주일간 16만번의 연산을 거듭한 결과 157자리의 숫자를 인수분해하는 데에 성공하였습니다. 엄청난 횟수의 연산이기는 하지만 이 정도의 연산으로 N이 소인수 분해될 수 있다면 RSA는 실용화될 수 없는 믿을 수 없는 암호체계가 되고 맙니다. 그러나 다행히도 그 소인수는 2의 523승에서 1을 뺀 수였는데 2의 n승에서 1을 뺀 소수는 쉽게 계산된다는 것이 알려졌습니다. 그 이후 RSA에 사용되는 N을 만드는 데에는 이러한 수는 제외되게 되었습니다.


  실제 사용하는 RSA 시스템은 굉장히 큰 N(큰 경우에는 300자리 이상)을 만들어 1 회사에서 1개의 N을 사용하기도 하는데 이 1개의 수로부터 많은 개수(N이 그렇게 클 경우에는 거의 무한한 개수)의 E와 D를 구하여 고객별로 다른 공개 key와 비밀 key를 제공하는 방법을 사용하고 있습니다. 위험은 피할 수 없는 것이 그 system 어딘가에는 N을 구성하는 p와 q가 들어가 있습니다. 세상에 완벽한 보안이란 역시 존재하지 않는 것 같습니다.



  PGP 맛보기


  PGP는 Pretty Good Privacy의 약자인데 RSA 팀이 만든 공개 프로그램입니다. 인터넷상에서 이 프로그램을 구할 수 있는 곳은 많습니다. 그 중 한 곳을 소개하면 다음과 같습니다.


  http://www.uni-mannheim.de/studorg/gahg/PGP


  이 프로그램은 1개의 N을 사용하는데 사용자가 컴퓨터의 지시에 따라 긴 문장을 타이핑하면 그 타이핑 리듬에 따라 E와 D를 결정합니다. 그리고 이를 이용하여 암호화, 복호, 디지털 서명을 할 수 있습니다.



  마무리


  제가 많은 분들이 생소하게 생각할 분야에 관하여 이런 글을 쓰는 이유 중의 하나는 다음과 같습니다. 현재 디지털 서명 시스템은 RSA에 의존하고 있을 뿐 아니라 다른 대안이 전혀 없기 때문에 우리나라가 디지털 서명 제도를 채택한다면 어쩔 수 없이 RSA에 의존할 수밖에 없습니다. 그 법제도를 만들고 운영해 갈 여러분들이 RSA의 이론적, 기술적 기초를 이해하고 있어야만 RSA의 안전성과 위험성에 대한 정당한 평가를 할 수 있을 것이고, 결국 정당한 정책적 판단을 할 수 있을 것이라고 믿기 때문입니다.


  또 다른 이유는 재미 때문입니다. 프랑스의 천재 수학가 Pierre de Fermat(페르마)의 현실세계에서의 직업이 판사였다는 것을 알고 계십니까? 법학이 연구대상으로 삼는 현실세계는 불확정성이론과 chaos이론이 적용되는 복잡계인 반면, 수학이 연구대상으로 삼는 가상의 세계는 지극히 단순한 세계여서 정연한 질서가 있습니다. 질서에는 아름다움이 있습니다. 현실적으로 복잡계에 존재하는 Fermat가 아름다운 질서를 연구하면서 재미를 찾았듯이 이 글을 읽는 분들 중에는 분명히 질서와 논리의 아름다움에 빠지는 재미를 아는 분들이 있을 것입니다.


  장차 RSA에 의하여 비밀이 유지되는 세상이 형성되면 그 세계의 안전은 전적으로 소수의 불규칙성에 의존하게 됩니다. 누군가가 소수에 존재하는 밝혀지지 않은 질서를 발견하게 된다면 그는 우주의 비밀까지는 아니더라도 이 세상 모든 사람의 비밀을, 어쩌면 이 세상 모든 사람의 돈까지도 손에 쥐게 될 것입니다. 물론 이 세상에는 대재앙이 되고 말 것입니다.



  덧붙임

  2001. 6. 28.자 동아일보에 "타원곡선 암호체계 뜬다"라는 제목에 "소수암호 해독 길 열려 30년 독점 끝 "이라는 부제를 단 기사(현재는 http://www.donga science.com/에서 보실 수 있는데, 시일이 지나면 회원가입을 하셔야 볼 수 있습니다)가 실렸기 때문에 이 글을 보완할 필요가 생겼습니다. 위 기사를 쓴 기자는 동아사이언스 기자인데 암호에 많은 관심을 갖고 있는 것 같고 저보다는 더 전문적인 지식을 갖고 있는 것 같습니다. 이 기사는 "도너츠 암호로 불리는 '타원곡선 암호'가 암호계의 터주대감인 소수 암호에 강력한 도전장을 던지고 있다. 도너츠 암호는 25∼27일 고등과학원에서 열린 암호론 학술대회에서 논문 발표의 60~70%를 차지할 정도로 뜨거운 관심을 모으는 등 암호의 역사를 고쳐 쓰고 있다" 그리고 이어서 "99년 네덜란드 학자들이 소수 암호칩을 해독하면서 난공불락의 성이 무너졌다. 이들은 당시 소수암호칩 제조 회사에서 2,000달러의 상금을 받기도 했다"라고 적고 있습니다.




  위 기사를 기회로 수학에 관한 조금 더 전문적인 언급을 하겠습니다.




  이 글에서도 소수를 찾아내는 방법으로 타원함수를 이용하는 방법이 있다는 언급을 하였습니다. 고등학교 수학을 공부한 사람은 누구나 알다시피 방정식은 함수로 표현될 수 있고 함수는 그래프상의 자취로 형상화될 수 있습니다. 따라서 타원방정식, 타원함수, 타원곡선은 모두 수학적 동의어로 사용될 수 있습니다. 19세기 수학을 거치면서 정수론에서는 밝혀질 수 있는 것은 모두 밝혀졌기 때문에 더 이상의 새로운 발견은 없을 것이라는 예상도 있었습니다만, 20세기에 들어 정수론은 그 예상을 뒤엎고 새로운 발전을 거듭하였는데 그 중 많은 것이 타원곡선과 관련됩니다.



  위 글에서도 언급하였던 프랑스의 판사 겸 수학자 Fermat는 바셰가 프랑스어로 번역한 Arithmetica(디오판토스의 저술로서 총 13권 중 6권만이 전해지고 있습니다. 유클리드의 The Elements에 비견되는 중요한 저술입니다) 8번 문제 여백에 다음과 같은 주석을 달았습니다.


  "임의의 세제곱수는 다른 두 세제곱수의 합으로 표현될 수 없다. 임의의 네제곱수 역시 다른 두 네제곱수의 합으로 표현될 수 없다. 일반적으로 3 이상의 지수를 자진 정수는 이와 동일한 지수를 가진 다른 두 수의 합으로 표현될 수 없다."


  그리고 그는 이어서 장난기 어린 다음과 같은 주석을 붙였습니다.


  "나는 경이적인 방법으로 이 정리를 증명하였다. 그러나 책의 여백이 너무 좁아 여기에 옮기지는 않겠다,"


  이 정리(또는 추측)가 300년 이상 전세계의 수많은 수학자들의 자존심을 여지없이 짓밟아 놓은 "페르마의 마지막 정리(Fermat's Last Theorem)"입니다.




  "페르마의 마지막 정리"는 많은 일화를 남겼는데 다음과 같은 믿어지지 않은 이야기도 있습니다.



  독일 다름슈타트 출신의 실업가인 Paul Wolfskehl은 실연으로 상심하여 자살을 결심하였습니다. 그는 먼저 죽기에 알맞은 날과 시간을 정한 후 모든 업무를 정리하고 가족들과 친구들에게 남기는 편지를 일일이 작성하였습니다. 마지막 편지를 마무리짓고 시계를 보니 아직도 자살할 시간에 몇 시간이 남아 있었습니다. 그는 자살 시간에 맞추기 위하여 서재에서 수학서적을 뒤적이다가 페르마의 마지막 정리에 관한 쿰머의 논문을 읽기 시작했습니다.  수학에 상당한 조예를 갖고 있던 그는 당 시대 최고수준의 수학자인 쿰머의 논문에 오류가 있음을 발견하고 이에 몰두하였습니다. 그 사이에 자살시간을 훨씬 지나 동이 트고 말았습니다. 결국 그는 생에 새로운 의미를 찾아 자살을 포기하는 대신 자신의 재산 대부분인 10만 마르크를 페르마의 마지막 정리를 증명하는 자에 대한 상금으로 기부하였습니다. 그 때가 1908년이었는데 위 상금을 기부 받은 괴팅겐의 왕립과학원은 2007. 9. 13.을 시한으로 한 현상광고를 하였습니다.

  1997. 6. 27. 위 상금은 수많은 수학자들의 박수를 받으면서 그리고 또 다른 많은 수학자들의 아쉬움 속에, 그리고 전 세계 아마추어 수학자들의 허탈감을 뒤로 한 채 영국의 수학자 Andrew Wiles(와일즈)에게 수여되었습니다.

  페르마의 마지막 정리의 증명을 담은 그의 논문은 "Modular elliptic curves and Fermat's last theorem"(우리말로 변역하면 "모듈형식의 타원곡선과 페르마의 마지막 정리"가 될 것입니다)라는 제목으로 "Annals of Mathematics" 141권 3호(1995. 3.)에 게재되었습니다. 위 잡지는 1884년 발간을 시작하여 현재는 미국 프린스턴 대학과 고등학술원(the Institute for Advanced Study)에 의하여 발간되고 있는 수학전문학술지입니다. ID가 없으면 그 내용에는 접근할 수 없지만 http://www.math.princeton.edu/~annals/으로 찾아가시면 보다 상세한 정보를 얻을 수 있습니다.



  암호를 말하다가 갑자기 왜 페르마의 마지막 정리를 장황하게 언급하였는가 그 이유를 말하면 페르마의 마지막 정리에 나온 문제는 정수론의 문제이면서 타원방정식 문제이고 동시에 modue 수학과 관련되기 때문입니다(module 수학이 타원곡선과 연결된 것은 일본의 수학자인 타니야마와 시무라의 업적입니다). Andrew Wiles의 증명은 정수론과 타원곡선과 module 수학을 하나로 엮은 대통일 수학의 출발점으로 평가됩니다.


  본론으로 돌아가 보면, 저는 타원곡선이 정확히 어떤 알고리즘을 사용하여 암호화와 복호를 수행하는지 알지 못합니다. 더욱이 그 암호 시스템이 대칭암호시스템인지 비대칭암호시스템인지(RSA처럼 암호화 key와 복호 key가 다른 시스템을 비대칭암호시스템이라고 합니다)도 알지 못합니다. 다만 타원곡선은 너무나 다양하고 비정형적이기 때문에(다양한 타원곡선 사이의 공통적 성질이 밝혀지지 않았다는 의미입니다) 암호에 사용될 수 있는 가능성은 오래전부터 제기되어 왔습니다.


  다만 위 기사는 "1999년 네덜란드 학자들이 소수암호칩을 해독하면서 난공불락의 성이 무너졌다"라고 적고 있는데 이에 대한 상세한 정보가 없어서 네덜란드의 학자들이 소수암호칩의 내용을 disassembling하는 데에 성공하였다는 것인지 아니면 N을 p와 q로 소인수분해하는 데에 성공하였다는 것인지 알 수 없습니다. 만일 후자라면 RSA 시스템의 보안성에 큰 문제가 되는 것이고, 전자라면 큰 문제가 아닙니다. RSA 시스템은 key 생성 시스템, 암호화 시스템, 복호 시스템의 3 시스템으로 구성될 수 있습니다.


  참고로 위에서 소개한 PGP는 초보적인 RSA 시스템이므로 3 시스템이 하나의 프로그램에 포함되어 있을 뿐입니다. RSA 시스템에서 p와 q는 key 생성 시스템에만 들어가 있을 뿐 암호화 시스템과 복호 시스템에는 들어가 있지 않기 때문에 암호화 시스템과 복호 시스템이 disassembling되는 것만으로는 N만을 알려질 뿐이고 key 생성 시스템이 유출되지 않는 이상 N을 소인수 하는 방법 외에는 p와 q를 알 수 있는 방법이 없습니다.


  이후에라도 보다 상세한 추가적인 정보를 접하게 되면 이 글을 보완하기로 약속하고 이만 줄이겠습니다.

(법원 웹진)

덧글쓰기 | 엮인글 쓰기 이 포스트를..  


             muse1472  ⓜⓤⓢⓔ①④⑦② RSA 알고리즘 개요  
            muse1472  ⓜⓤⓢⓔ①④⑦② RSA 알고리즘 개요      
▲ 이전글 - 베다 수학 (Vedic Maths)  전체 포스트 보기  
▼ 다음글 - 백년에한번나올까말까한영웅(박정희)  

'KB > C/C++' 카테고리의 다른 글

code profiler  (0) 2006.04.17
함수 링크 순서 정해주기  (0) 2005.10.28
RSA를 이해하기 위한 코드  (0) 2005.03.25
[펌] vc 5, 6 stl 버그 픽스  (0) 2004.09.10
[펌] C++ Reverse Disassembly  (0) 2004.09.10
[stl] 소트 하기  (0) 2004.03.19
YOUR COMMENT IS THE CRITICAL SUCCESS FACTOR FOR THE QUALITY OF BLOG POST


http://www.dinkumware.com/vc_fixes.html


Fixes for Library Bugs in VC++ V5.0/V6.0

(as of 10 Nov 02)

---

The following bug fixes correct problems in the Standard C++ Library that accompanies Microsoft Visual C++ V5.0 and V6.0. Each replacement header file supplied here is represented as a .txt file, so you can view it directly with a web browser. You can also install the replacement file directly from the browser while you are viewing it -- simply select File/Save As File and store the file with the appropriate name in the include directory. YOU ARE STRONGLY ENCOURAGED TO SAVE THE EXISTING HEADER BEFORE OVERWRITING IT.

For example, to replace the header <deque> in a typical VC++ V5.0 installation, choose the directory:

c:\Program Files\DevStudio\VC\include
and save the file with the name deque. Note that some browsers insist on saving the file with the name deque.txt, in which case you will have to rename the file after saving it from the browser.

Be warned that updating a header file does not necessarily trigger a recompilation. You may have to force a rebuild to see the effect of a change.

Note also that some header-file information is captured in DLLs supplied by Microsoft. If you encounter a conflict, you must either avoid using the DLL (by linking statically) or rebuild the offending DLL. We still can supply no information on how to rebuild the standard DLLs shipped with VC++. (Microsoft insists that it's too difficult to describe.)

It is always a good idea to apply the latest Microsoft service pack to upgrade your compiler. Many problems quietly disappear when you do so. For example, you can now get V5.0 SP3 and V6.0 SP3.

DISCLAIMER
The files presented here are copyright ?1995-2000 by P.J. Plauger. All rights reserved. They are for use only in conjunction with a valid license for Microsoft Visual C++ V5.0 or V6.0. Microsoft Corporation is in no way involved with the production or release of these files. The files are offered on an ``as is'' basis. DINKUMWARE, LTD. AND P.J. PLAUGER MAKE NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THESE FILES, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. DINKUMWARE, LTD. AND P.J. PLAUGER SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING THESE FILES.


--------------------------------------------------------------------------------

Fix to <algorithm>
The internal template algorithm _Buffered_merge (two versions) fails to initialize local variables in two places. Change the code as indicated by the comments:

    if (_D2 < _D1)
        {_D1n = _D1 / 2, _D2n = 0;    // clear _D2n
        _Fn = _F;
        advance(_Fn, _D1n);
        _Ln = lower_bound(_M, _L, *_Fn);
        _Distance(_M, _Ln, _D2n); }
    else
        {_D1n = 0, _D2n = _D2 / 2;    // clear _D1n
        _Ln = _M;
        advance(_Ln, _D2n);
        _Fn = upper_bound(_F, _M, *_Ln);
        _Distance(_F, _Fn, _D1n); }
And for the version with predicate:

    if (_D2 < _D1)
        {_D1n = _D1 / 2, _D2n = 0;    // clear _D2n
        _Fn = _F;
        advance(_Fn, _D1n);
        _Ln = lower_bound(_M, _L, *_Fn, _P);
        _Distance(_M, _Ln, _D2n); }
    else
        {_D1n = 0, _D2n = _D2 / 2;    // clear _D1n
        _Ln = _M;
        advance(_Ln, _D2n);
        _Fn = upper_bound(_F, _M, *_Ln, _P);
        _Distance(_F, _Fn, _D1n); }
Fixes to <deque>
The header <deque> (updated 18 October 1999 to V2.33, the latest shipped version) presented here corrects a problem with the representation of the iterator that designates the end of the controlled sequence. If the sequence exactly fills the last allocated block, incrementing the iterator that designates the last element can yield a value that does not match the value returned by end(). The larger the elements stored in the container, the more likely this situation will arise.

The fix is to ensure that every iterator has just one possible representation. For added security, the ends of the container are now guarded with null map pointers. It is no longer possible to step an iterator off either end of the sequence. (Such protection is not required by the C++ Standard, but it makes for nicer failure modes in buggy code.)

Fix to <fstream>
(Added 13 October 1999.) The header <fstream> defines template class basic_filebuf (among other things. Its member function _Init contains a bug that causes files opened by name to disable buffering unnecessarily, resulting in a serious degradation of performance. Change the test:

if (_Fp != 0 && !_Closef && sizeof (_E) == 1)
to:

if (_Fp != 0 && sizeof (_E) == 1)
to eliminate this problem.

Fix to <istream>
The header <istream> contains a definition for member function basic_istream::getline. It has a lookahead problem -- typing a delimiter to end the input doesn't return control until you type yet another character. Change the code as indicated by the comment:

    else if (_C == _Di)
        {++_Chcount;
        rdbuf()->snextc();    // replace snextc with sbumpc
        break; }
Note that V6.0 replaces snextc with stossc. It is an adequate fix, but you can also apply the above patch safely.

Fix to <list>
(updated 7 July 1998) Both versions of the member function list::sort misplace elements if asked to sort a container with more than 32,768 elements. To fix the first version, change the code as indicated by the comment:

        if (_I == _MAXN)
            _A[_I].merge(_X);
    // SHOULD BE    _A[_I - 1].merge(_X);
Also change the corresponding line in the second version:

        if (_I == _MAXN)
            _A[_I].merge(_X, _Pr);
    // SHOULD BE    _A[_I - 1].merge(_X, _Pr);
You might also consider increasing _MAXN from 15 to, say 25. That way, you would have to sort a list of more than 32 million elements, instead of 32 thousand, before the performance begins to degrade.

Fix to <memory>
Template class auto_ptr creates two owners for an object if you copy an auto_ptr object back to a previous owner that still stores the same object pointer. To eliminate this problem, change the code in auto_ptr::operator= as indicated by the comment:

    else if (_Y._Owns)
        _Owns = true;    // _Owns = true, _Y.release();
Note that this template class has been redesigned more than once since this version of the library was frozen. No attempt is made here to track those changes.

Fix to <sstream>
(Added 12 November 1999.) Class basic_stringbuf grows its buffer by fixed-size increments, which can be very slow if the buffer gets very large. To grow the buffer exponentially, replace the line in basic_stringbuf::overflow that reads:

    size_t _Ns = _Os + _Alsize;
with:

    size_t _Ns = (_Os < _Alsize) ? _Os + _Alsize : 2 * _Os + 1;
Fix to <string>
The header <string> contains a definition for template function getline. It has a lookahead problem -- typing a delimiter to end the input doesn't return control until you type yet another character. Change the code as indicated by the comment:

    else if (_Tr::eq(_C, _D))
        {_Chg = true;
        _I.rdbuf()->snextc();    // replace snextc with sbumpc
        break; }
Fix to <vector>
The header <vector> sometimes fails to extend a vector properly. In two versions ofinsert, change the code as shown:

        _Destroy(_First, _Last);
        allocator.deallocate(_First, _End - _First);
        _End = _S + _N;
        _Last = _S + size() + _M;
        _First = _S; }

        _Destroy(_First, _Last);
        size_type _O = size();    // add this statement
        allocator.deallocate(_First, _End - _First);
        _End = _S + _N;
        _Last = _S + _O + _M;    // was _Last = _S + size() + _M;
        _First = _S; }
Fix to <xmemory>
Template class _Destroy has an unfortunate interaction with a bug in the VC++ compiler. It gets confused if you ask it to destroy an object of a class that defines the name _Ty. (Template class complex is one such creature.) The best workaround is to replace the template parameter _Ty with a really strange name, as in:

        // TEMPLATE FUNCTION _Destroy
template<class _Xyzzy> inline
    void _Destroy(_Xyzzy _FARQ *_P)
    {_DESTRUCTOR(_Xyzzy, _P); }
Fixes to <xstring>
The header <xstring> (original 25 May 1998) presented here corrects a problem with string assignments. Assigning a shorter sequence to an existing string can cause the old string to be copied in full to the newly allocated area, thus causing a storage overwrite, and an occasional storage leak as a result. In rarer circumstances, a string is partially altered by a replace member function before the copy on write occurs, thus causing changes to an apparently unrelated string object.

The fix is a small but significant change to the private member function _Grow. Several calls to _Freeze, to force a copy on write, are also added.

Please note that this implementation is still not as thread safe as it should be, because of the reference-counted implementation. A write to a ``copy'' of a string in one thread can confuse a read of that string in another thread, because the two still secretly share the same representation. One way to ensure that the non-const string str has a private representation is to call str.begin(). (By creating a mutable iterator into the string, you rule out sharing of representations.) Another way is to disable reference-counting altogether, making string operations thread safe. Simply change the value of _FROZEN to zero:

    enum _Mref {_FROZEN = 255};  // set to zero to disable sharing
Fix to <xtree>
The header <xtree> (original 25 June 1998) presented here eliminates all need for thread locks and corrects a number of thread-safety issues for template classes map, multimap, set, and multiset. It also solves some nasty problems with sharing these classes across DLLs. Note that no attempt has been made to retrofit the changes needed to make these template classes exception safe in the sense required by the final C++ Standard. (The headers map and set once presented here have been dropped as of 4 April 1999 -- they were effectively unchanged over the shipped versions.)

Fix to strftime.c
The Microsoft C library file strftime.c (original 28 March 2000) fails to supply locale information needed for the %X conversion specifier used by template class time_put. To fix the problem, add the missing line shown below to the function _Gettnames. Change the code from:

    s += strlen(strcpy(s, pt->ww_ldatefmt)) + 1;
    pn->ww_timefmt = s; }
to:

    s += strlen(strcpy(s, pt->ww_ldatefmt)) + 1;
    pn->ww_timefmt = s;
    strcpy(s, pt->ww_timefmt); }
NB: You need to make this change even if you licensed the v3.08 upgrade library from Dinkumware. We do not supply a replacement for it.

'KB > C/C++' 카테고리의 다른 글

함수 링크 순서 정해주기  (0) 2005.10.28
RSA를 이해하기 위한 코드  (0) 2005.03.25
[펌] vc 5, 6 stl 버그 픽스  (0) 2004.09.10
[펌] C++ Reverse Disassembly  (0) 2004.09.10
[stl] 소트 하기  (0) 2004.03.19
C++ Casting  (0) 2004.03.19
YOUR COMMENT IS THE CRITICAL SUCCESS FACTOR FOR THE QUALITY OF BLOG POST


http://thecodeproject.com/cpp/reversedisasm.asp

'KB > C/C++' 카테고리의 다른 글

RSA를 이해하기 위한 코드  (0) 2005.03.25
[펌] vc 5, 6 stl 버그 픽스  (0) 2004.09.10
[펌] C++ Reverse Disassembly  (0) 2004.09.10
[stl] 소트 하기  (0) 2004.03.19
C++ Casting  (0) 2004.03.19
[stl] STL List를 사용하기  (0) 2004.03.19
YOUR COMMENT IS THE CRITICAL SUCCESS FACTOR FOR THE QUALITY OF BLOG POST


[stl] 소트 하기

KB/C/C++ 2004.03.19 16:41
오후 2:10 2002-08-13
조경민 bro@shinbiro.com
======================================================

#include <functional>
#include <algorithm>
#include <vector>

// User-defined predicate function for sorting.
struct Data
{
long Position;
};

std::vector<Data>        m_vecDatas;                // 소속 리스트

소트 비교 정의
struct SortPossition : public std::greater<Data>
{
    bool operator()(const Data &pfi1, const Data &pfi2) const
    {
        return pfi1.Position < pfi2.Position;
    }
};


소트하기
std::sort( m_vecDatas.begin(), m_vecDatas.end(), SortPossition()

'KB > C/C++' 카테고리의 다른 글

[펌] vc 5, 6 stl 버그 픽스  (0) 2004.09.10
[펌] C++ Reverse Disassembly  (0) 2004.09.10
[stl] 소트 하기  (0) 2004.03.19
C++ Casting  (0) 2004.03.19
[stl] STL List를 사용하기  (0) 2004.03.19
[stl] 이중배열 만들기 vector  (0) 2004.03.19
YOUR COMMENT IS THE CRITICAL SUCCESS FACTOR FOR THE QUALITY OF BLOG POST


C++ Casting

KB/C/C++ 2004.03.19 16:33
C++ Casting
조경민 오전 1:54 2001-05-03
=-=======================================

dynamic, static은 클래스 hirachy cast에 쓰이는데
dynamic_cast는 변환 불가하면 zero로 세팅하고
static_cast는 변환불가시 assert 에러가 떨어진다.

CSon* lpSon = (CSon*)lpBase;
=>
CSon* lpSon = dynamic_cast<CSon*>(lpBase);
if( lpSon != NULL )
   lpSon->fnSon();
*downcast시 알맞지 않으면 lpSon == NULL이 된다.
*ambiguass 한 캐스트시 에러가난다.
*cross cast에 쓰일수 있다.

[A]  [A]
|      |
[B] [C] [D]
+---+---+
     |
    [E]

void f(D* pd)
{
  E* pe = dynamic_cast<E*>(pd);
  B* pb = pe;                   // upcast , implicit conversion
  A* pa = pb;                   //              "
}

void f(D* pd)
{
  B* pb = dynamic_cast<B*>(pd); // cross cast
  A* pa = pb;                   // upcast implicit 가능
}

---------------------------------------------------------

CBase* lpBase = (CBase*)lpSon;
=>
CBase* lpBase = static_cast<CBase*>(lpSon);
// 만일 lpBase가 실제 base가 아니면 컴파일타임에러가남





이외의 것
reinterpreted_cast<>를 쓴다.

'KB > C/C++' 카테고리의 다른 글

[펌] C++ Reverse Disassembly  (0) 2004.09.10
[stl] 소트 하기  (0) 2004.03.19
C++ Casting  (0) 2004.03.19
[stl] STL List를 사용하기  (0) 2004.03.19
[stl] 이중배열 만들기 vector  (0) 2004.03.19
STL String  (0) 2004.03.19
YOUR COMMENT IS THE CRITICAL SUCCESS FACTOR FOR THE QUALITY OF BLOG POST


오전 9:14 2000-05-02
조경민 STL List를 사용하기
-------------------------------------------------
아래처럼 하면된다.
#include <list>
using namespace std;
:
        list<int> L;
        list<int>::iterator  Lt;

        L.push_back(0);
        L.push_front(1);
        Lt = L.begin();

        CString str;

        for( ; Lt != L.end() ; ++Lt) {
                str.Format("%d",*Lt);
                AfxMessageBox(str);
        }
리스트 컨테이너 노드는 알아서 소거하지만 안의 내용물을
내가new 해서 만들었다면 그것은 내가 delete해주어야 한다.
Like A CPtrList


Thanks to 병창형

#pragma warning(disable:4786)
#include <stdio.h>
#include <iostream.h>
#include <string>
#include <list>
#include <algorithm>

using namespace std;

void main()
{

        cout << "-----------------------------" << endl;
        cout << " Sample " << endl;
        cout << "-----------------------------" << endl;

        list<int>  ml_stlData;
        list<int>::iterator  ml_GetIt;


        ml_stlData.push_back(1);
        ml_stlData.push_back(3);
        ml_stlData.push_back(4);

    
        ml_GetIt = ml_stlData.begin();

        for(ml_GetIt ; ml_GetIt != ml_stlData.end() ; ++ml_GetIt) {


                 cout << "Data : " << *ml_GetIt << endl;

        }

        cout << "-----------------------------" << endl;
        cout << " Terminate Program" << endl;
        cout << "-----------------------------" << endl;

        getchar();

}

'KB > C/C++' 카테고리의 다른 글

[stl] 소트 하기  (0) 2004.03.19
C++ Casting  (0) 2004.03.19
[stl] STL List를 사용하기  (0) 2004.03.19
[stl] 이중배열 만들기 vector  (0) 2004.03.19
STL String  (0) 2004.03.19
Boyer Moore 문자열 패턴 매칭  (0) 2004.03.19
YOUR COMMENT IS THE CRITICAL SUCCESS FACTOR FOR THE QUALITY OF BLOG POST


조경민
이중배열 만들기 vector

오후 12:51 2000-05-12
====================================================
다음처럼 vector 를 겹치면 이중 배열을 생성할 수 있다. (동적 이중배열)
실제 안의 값은 VARIANT로 했다.

vector<        vector< VARIANT > >                arrData;


        void        fnSetData( int nRow, int nCol, VARIANT& varValue );
        void        fnSetData( int nRow, int nCol, double dblValue );


void _tagSTCHART_DATA::fnSetData( int nRow, int nCol, double dblValue )
{
        VARIANT varValue;
        varValue.vt = VT_R8;
        varValue.dblVal = dblValue;
        fnSetData( nRow, nCol, varValue);
}

void _tagSTCHART_DATA::fnSetData( int nRow, int nCol, VARIANT& varValue )
{
        // 디폴트 값을 설정한후
        static VARIANT varEmpty = { VT_EMPTY, };
        
        // 현재 행의 크기를 얻어온다.
        int nSize = arrData.size();
        if( nSize <= nRow )    // 행보다 큰 값으로 값을 넣으려면 vector
                               // resize를 해야 한다.
                arrData.resize( nRow + 5 );
        // 그 행에 대한 열의 크기를 얻어온다.
        nSize = arrData[nRow].size();
        if( nSize <= nCol ) // 역시 rezinge 코드
                arrData[nRow].resize( nCol + 5 , varEmpty );
                // varEmpty는 실제 VARIANT에 리사이징후 새로만들어진
                // VARIANT들에게 들어가는 디폴트 값이 된다.

        // 그런후 자기가 넣고 싶은 행열에 값을 넣은다.
        arrData[nRow][nCol] = varValue;

        // VARIANT타입이 Double형이라면        어떤 일을 한다.
        if( varValue.vt == VT_R8 )
                fnCheckMiniMax( varValue.dblVal );

        if( nCol >= nMaxLegend )
                nMaxLegend = nCol+1;
        if( nRow >= nMaxSeries )
                nMaxSeries = nRow+1;

}

'KB > C/C++' 카테고리의 다른 글

C++ Casting  (0) 2004.03.19
[stl] STL List를 사용하기  (0) 2004.03.19
[stl] 이중배열 만들기 vector  (0) 2004.03.19
STL String  (0) 2004.03.19
Boyer Moore 문자열 패턴 매칭  (0) 2004.03.19
라인위의점으로선택  (0) 2004.03.19
YOUR COMMENT IS THE CRITICAL SUCCESS FACTOR FOR THE QUALITY OF BLOG POST


티스토리 툴바